@hraness/kb 0.17.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 (200) hide show
  1. package/DISCLOSURE +43 -0
  2. package/LICENSE +21 -0
  3. package/README.md +545 -0
  4. package/dist/agent-context.js +35 -0
  5. package/dist/agent-guide-audit.js +18 -0
  6. package/dist/attachments.js +19 -0
  7. package/dist/authoring.js +33 -0
  8. package/dist/benchmark.js +19 -0
  9. package/dist/capture.js +49 -0
  10. package/dist/cli.js +3646 -0
  11. package/dist/clip/acquire.js +57 -0
  12. package/dist/clip/args.js +21 -0
  13. package/dist/clip/bounded-byte-buffer.js +9 -0
  14. package/dist/clip/browser-profiles.js +17 -0
  15. package/dist/clip/bundle-reader.js +11 -0
  16. package/dist/clip/cli.js +27 -0
  17. package/dist/clip/cookies.js +21 -0
  18. package/dist/clip/defuddle-worker.js +84 -0
  19. package/dist/clip/doctor.js +32 -0
  20. package/dist/clip/jobs.js +784 -0
  21. package/dist/clip/network-proxy.js +9 -0
  22. package/dist/clip/network.js +28 -0
  23. package/dist/clip/persist.js +30 -0
  24. package/dist/clip/refresh.js +11 -0
  25. package/dist/clip/terminal.js +11 -0
  26. package/dist/evaluation-builder.js +12238 -0
  27. package/dist/evaluation-kb.js +26 -0
  28. package/dist/evaluation.js +35 -0
  29. package/dist/git.js +39 -0
  30. package/dist/graph.js +39 -0
  31. package/dist/index-01jj6rbv.js +1103 -0
  32. package/dist/index-06c9ctr6.js +738 -0
  33. package/dist/index-0kavxzqj.js +2480 -0
  34. package/dist/index-1gwbassd.js +743 -0
  35. package/dist/index-1n418kb9.js +827 -0
  36. package/dist/index-1vrd1rmn.js +56 -0
  37. package/dist/index-1xxnjn0d.js +171 -0
  38. package/dist/index-3rm7cz6h.js +373 -0
  39. package/dist/index-3v2z4f0q.js +328 -0
  40. package/dist/index-48pz4jpc.js +392 -0
  41. package/dist/index-4j3tt0c3.js +234 -0
  42. package/dist/index-5n05se68.js +307 -0
  43. package/dist/index-5vwpzb5a.js +764 -0
  44. package/dist/index-6g2pv9d2.js +370 -0
  45. package/dist/index-7fzc32gf.js +712 -0
  46. package/dist/index-84x0vjjp.js +432 -0
  47. package/dist/index-adx6khj5.js +488 -0
  48. package/dist/index-b88v3vtm.js +805 -0
  49. package/dist/index-cv6fh7z5.js +462 -0
  50. package/dist/index-cxfrakt7.js +1067 -0
  51. package/dist/index-d13v9ckt.js +150 -0
  52. package/dist/index-dycjbhw2.js +1943 -0
  53. package/dist/index-dyqwejk5.js +531 -0
  54. package/dist/index-e5fbsywq.js +658 -0
  55. package/dist/index-f984hw45.js +927 -0
  56. package/dist/index-gh719d91.js +63 -0
  57. package/dist/index-hgve9rh2.js +2046 -0
  58. package/dist/index-hya40gb2.js +474 -0
  59. package/dist/index-j4zgmzjr.js +152 -0
  60. package/dist/index-jsmvyyvf.js +1166 -0
  61. package/dist/index-kh0pwvdd.js +1974 -0
  62. package/dist/index-mqx4nd6v.js +119 -0
  63. package/dist/index-mxxxytys.js +1254 -0
  64. package/dist/index-n5dd7r0v.js +711 -0
  65. package/dist/index-npg9z1a4.js +431 -0
  66. package/dist/index-pj501bh1.js +140 -0
  67. package/dist/index-qry4vhxk.js +1041 -0
  68. package/dist/index-s2gw5aw9.js +199 -0
  69. package/dist/index-vvdj6kca.js +70 -0
  70. package/dist/index-w2zc0vwa.js +571 -0
  71. package/dist/index-x3fthpsc.js +585 -0
  72. package/dist/index-zr53sf63.js +44 -0
  73. package/dist/index-zxdy5pby.js +2728 -0
  74. package/dist/index-zzhgcwyt.js +966 -0
  75. package/dist/index.js +453 -0
  76. package/dist/navigation.js +13 -0
  77. package/dist/pdf.js +85 -0
  78. package/dist/percolate.js +24 -0
  79. package/dist/portfolio.js +77 -0
  80. package/dist/query.js +29 -0
  81. package/dist/repository-memory.js +60 -0
  82. package/dist/sdk.js +36 -0
  83. package/dist/search-rules.js +34 -0
  84. package/dist/search.js +22 -0
  85. package/dist/semantic.js +39 -0
  86. package/dist/source-inbox.js +17 -0
  87. package/dist/untrusted-content.js +32 -0
  88. package/dist/url-intelligence.js +74 -0
  89. package/dist/workflow.js +23 -0
  90. package/dist/workflows/decision-context.js +20 -0
  91. package/dist/workflows/explain-change.js +8 -0
  92. package/dist/workflows/index.js +28 -0
  93. package/dist/workflows/plan-radar.js +10 -0
  94. package/package.json +409 -0
  95. package/skills/kb/AGENTS.md +19 -0
  96. package/skills/kb/SKILL.md +82 -0
  97. package/skills/kb/agents/openai.yaml +4 -0
  98. package/skills/kb/references/pdf-review.md +51 -0
  99. package/skills/kb/references/percolate.md +144 -0
  100. package/skills/kb/references/plan-structure.md +105 -0
  101. package/skills/kb/references/plan.md +115 -0
  102. package/skills/kb/references/query.md +231 -0
  103. package/skills/kb/references/refresh.md +133 -0
  104. package/skills/kb/references/save-pdf.md +125 -0
  105. package/skills/kb/references/save-url.md +178 -0
  106. package/skills/kb/references/url-authentication.md +75 -0
  107. package/skills/kb/references/url-platforms.md +25 -0
  108. package/src/agent-context.ts +1241 -0
  109. package/src/agent-guide-audit.ts +750 -0
  110. package/src/attachments.ts +723 -0
  111. package/src/authoring.ts +1725 -0
  112. package/src/benchmark.ts +362 -0
  113. package/src/capture.ts +68 -0
  114. package/src/cli.ts +3660 -0
  115. package/src/clip/acquire.ts +1273 -0
  116. package/src/clip/archive-today.ts +402 -0
  117. package/src/clip/args.ts +423 -0
  118. package/src/clip/assets.ts +262 -0
  119. package/src/clip/bounded-byte-buffer.ts +75 -0
  120. package/src/clip/browser-profiles.ts +372 -0
  121. package/src/clip/bundle-reader.ts +608 -0
  122. package/src/clip/capture.ts +1054 -0
  123. package/src/clip/cli.ts +181 -0
  124. package/src/clip/cookies.ts +512 -0
  125. package/src/clip/doctor.ts +1110 -0
  126. package/src/clip/extract.ts +868 -0
  127. package/src/clip/jobs.ts +959 -0
  128. package/src/clip/lib.ts +861 -0
  129. package/src/clip/media.ts +1474 -0
  130. package/src/clip/metadata-search-tool/Cargo.lock +2498 -0
  131. package/src/clip/metadata-search-tool/Cargo.toml +18 -0
  132. package/src/clip/metadata-search-tool/runner.ts +685 -0
  133. package/src/clip/metadata-search-tool/src/main.rs +389 -0
  134. package/src/clip/metadata-search.ts +687 -0
  135. package/src/clip/network-proxy.ts +627 -0
  136. package/src/clip/network.ts +950 -0
  137. package/src/clip/package-root.ts +54 -0
  138. package/src/clip/persist.ts +1472 -0
  139. package/src/clip/platforms.ts +1824 -0
  140. package/src/clip/refresh.ts +197 -0
  141. package/src/clip/structured.ts +432 -0
  142. package/src/clip/terminal.ts +197 -0
  143. package/src/clip/url-intelligence.ts +581 -0
  144. package/src/clip/url-metadata-backfill.ts +616 -0
  145. package/src/clip/url-metadata-cli.ts +251 -0
  146. package/src/clip/url-metadata.ts +1397 -0
  147. package/src/evaluation-analysis-v2.ts +1440 -0
  148. package/src/evaluation-builder.ts +2539 -0
  149. package/src/evaluation-corpus-authoring.ts +2052 -0
  150. package/src/evaluation-evidence.ts +1147 -0
  151. package/src/evaluation-execution-v2.ts +426 -0
  152. package/src/evaluation-implementation.ts +131 -0
  153. package/src/evaluation-kb-closure.ts +1430 -0
  154. package/src/evaluation-kb-runner-v2.ts +735 -0
  155. package/src/evaluation-kb-v2.ts +2567 -0
  156. package/src/evaluation-kb.ts +1018 -0
  157. package/src/evaluation-measurement-v2.ts +1462 -0
  158. package/src/evaluation-packing-v2.ts +452 -0
  159. package/src/evaluation-redaction.ts +28 -0
  160. package/src/evaluation-v2.ts +3857 -0
  161. package/src/evaluation.ts +1220 -0
  162. package/src/git.ts +1276 -0
  163. package/src/graph.ts +1487 -0
  164. package/src/index.ts +20 -0
  165. package/src/init.ts +123 -0
  166. package/src/navigation.ts +277 -0
  167. package/src/note-lock.ts +529 -0
  168. package/src/pdf/args.ts +202 -0
  169. package/src/pdf/capture.ts +298 -0
  170. package/src/pdf/cli.ts +159 -0
  171. package/src/pdf/extract.ts +303 -0
  172. package/src/pdf/layout.ts +618 -0
  173. package/src/pdf/markdown.ts +154 -0
  174. package/src/pdf/model.ts +234 -0
  175. package/src/pdf/ocr.ts +190 -0
  176. package/src/pdf/persist.ts +314 -0
  177. package/src/pdf/source.ts +135 -0
  178. package/src/pdf/tools.ts +146 -0
  179. package/src/pdf.ts +92 -0
  180. package/src/percolate.ts +877 -0
  181. package/src/portfolio-audit.ts +574 -0
  182. package/src/portfolio-identity.ts +162 -0
  183. package/src/portfolio-registry.ts +473 -0
  184. package/src/portfolio.ts +765 -0
  185. package/src/query.ts +646 -0
  186. package/src/repository-memory.ts +1150 -0
  187. package/src/sdk.ts +1452 -0
  188. package/src/search-rules.ts +712 -0
  189. package/src/search.ts +710 -0
  190. package/src/semantic-runtime.ts +1139 -0
  191. package/src/semantic.ts +2480 -0
  192. package/src/source-inbox.ts +232 -0
  193. package/src/untrusted-content.ts +401 -0
  194. package/src/url-intelligence.ts +104 -0
  195. package/src/vault.ts +636 -0
  196. package/src/workflow.ts +653 -0
  197. package/src/workflows/decision-context.ts +81 -0
  198. package/src/workflows/explain-change.ts +73 -0
  199. package/src/workflows/index.ts +3 -0
  200. package/src/workflows/plan-radar.ts +101 -0
@@ -0,0 +1,711 @@
1
+ // @bun
2
+ import {
3
+ MAX_SEARCH_RESULTS,
4
+ openKnowledgeBase
5
+ } from "./index-zzhgcwyt.js";
6
+ import {
7
+ scanVault
8
+ } from "./index-zxdy5pby.js";
9
+ import {
10
+ runGitCommand
11
+ } from "./index-1gwbassd.js";
12
+ import {
13
+ MAX_EVALUATION_EVIDENCE_BYTES,
14
+ redactEvaluationMachinePaths
15
+ } from "./index-b88v3vtm.js";
16
+ import {
17
+ MAX_REPOSITORY_MEMORY_DETAIL_LIMIT,
18
+ MAX_REPOSITORY_MEMORY_GROUP_LIMIT,
19
+ buildRepositoryMemoryContext,
20
+ repositoryMemoryGroupKeys
21
+ } from "./index-06c9ctr6.js";
22
+ import {
23
+ inspectAgentContextRepository
24
+ } from "./index-5vwpzb5a.js";
25
+
26
+ // src/evaluation-kb.ts
27
+ import { realpath, stat } from "fs/promises";
28
+ import { isAbsolute, relative, resolve, sep } from "path";
29
+ var objectIdPattern = /^[0-9a-f]{40}(?:[0-9a-f]{24})?$/u;
30
+ var SNAPSHOT_GIT_TIMEOUT_MS = 1e4;
31
+ var SNAPSHOT_GIT_OUTPUT_BYTES = 64 * 1024;
32
+ var DIAGNOSTIC_MESSAGE_BYTES = 16 * 1024;
33
+ var knowledgeBaseEvaluationRetrieverIds = Object.freeze([
34
+ "exact",
35
+ "keyword",
36
+ "semantic",
37
+ "hybrid",
38
+ "metadata",
39
+ "graph",
40
+ "path-context",
41
+ "git"
42
+ ]);
43
+
44
+ class FrozenEvaluationSnapshotError extends Error {
45
+ constructor(message, options) {
46
+ super(message, options);
47
+ this.name = "FrozenEvaluationSnapshotError";
48
+ }
49
+ }
50
+ function pathIsWithin(root, candidate) {
51
+ const fromRoot = relative(root, candidate);
52
+ return fromRoot === "" || fromRoot !== ".." && !fromRoot.startsWith(`..${sep}`) && !isAbsolute(fromRoot);
53
+ }
54
+ function decodedOutput(output, label, maximumBytes = SNAPSHOT_GIT_OUTPUT_BYTES) {
55
+ const bytes = typeof output === "string" ? Buffer.from(output, "utf8") : Buffer.from(output);
56
+ if (bytes.byteLength > maximumBytes) {
57
+ throw new FrozenEvaluationSnapshotError(`${label} exceeded the ${maximumBytes.toLocaleString("en-US")}-byte output limit.`);
58
+ }
59
+ return bytes.toString("utf8");
60
+ }
61
+ async function gitOutput(runGit, repository, args, label) {
62
+ const result = await runGit({
63
+ arguments: args,
64
+ cwd: repository,
65
+ timeoutMs: SNAPSHOT_GIT_TIMEOUT_MS,
66
+ maxOutputBytes: SNAPSHOT_GIT_OUTPUT_BYTES
67
+ });
68
+ if (result.status !== "ok") {
69
+ throw new FrozenEvaluationSnapshotError(`${label} could not be verified: ${result.status === "unavailable" ? result.message : result.message}`);
70
+ }
71
+ return decodedOutput(result.stdout, label);
72
+ }
73
+ function gitObjectId(output, label) {
74
+ const value = output.trim();
75
+ if (!objectIdPattern.test(value)) {
76
+ throw new FrozenEvaluationSnapshotError(`${label} returned a malformed Git object ID.`);
77
+ }
78
+ return value;
79
+ }
80
+ async function verifyFrozenEvaluationSnapshot(options) {
81
+ const resolveRealpath = options.realpath ?? realpath;
82
+ const readStat = options.stat ?? stat;
83
+ const repository = await resolveRealpath(resolve(options.repository));
84
+ const repositoryState = await readStat(repository);
85
+ if (!repositoryState.isDirectory()) {
86
+ throw new FrozenEvaluationSnapshotError("The evaluation repository must be a directory.");
87
+ }
88
+ const root = await resolveRealpath(resolve(options.root));
89
+ const rootState = await readStat(root);
90
+ if (!rootState.isDirectory()) {
91
+ throw new FrozenEvaluationSnapshotError("The evaluation vault root must be a directory.");
92
+ }
93
+ if (!pathIsWithin(repository, root)) {
94
+ throw new FrozenEvaluationSnapshotError("The evaluation vault root must resolve inside the repository.");
95
+ }
96
+ const declaredRoot = await resolveRealpath(resolve(repository, options.corpus.frozen.vaultRoot));
97
+ if (!pathIsWithin(repository, declaredRoot) || declaredRoot !== root) {
98
+ throw new FrozenEvaluationSnapshotError("The evaluation vault root must resolve to frozen.vaultRoot inside the repository.");
99
+ }
100
+ const runGit = options.runGit ?? runGitCommand;
101
+ const repositoryPrefix = (await gitOutput(runGit, repository, ["rev-parse", "--show-prefix"], "Git repository root")).trim();
102
+ if (repositoryPrefix !== "") {
103
+ throw new FrozenEvaluationSnapshotError(`The evaluation repository must be the Git working-tree root; Git reported prefix ${JSON.stringify(repositoryPrefix)}.`);
104
+ }
105
+ const head = gitObjectId(await gitOutput(runGit, repository, ["rev-parse", "--verify", "HEAD"], "Git HEAD"), "Git HEAD");
106
+ if (head !== options.corpus.frozen.repositoryCommit) {
107
+ throw new FrozenEvaluationSnapshotError(`Frozen repository commit ${options.corpus.frozen.repositoryCommit} does not match HEAD ${head}.`);
108
+ }
109
+ const vaultRevision = options.corpus.frozen.vaultRoot === "." ? "HEAD^{tree}" : `HEAD:${options.corpus.frozen.vaultRoot}`;
110
+ const vaultTree = gitObjectId(await gitOutput(runGit, repository, ["rev-parse", "--verify", vaultRevision], "Git vault tree"), "Git vault tree");
111
+ if (vaultTree !== options.corpus.frozen.vaultTree) {
112
+ throw new FrozenEvaluationSnapshotError(`Frozen vault tree ${options.corpus.frozen.vaultTree} does not match ${vaultRevision} ${vaultTree}.`);
113
+ }
114
+ const objectType = (await gitOutput(runGit, repository, ["cat-file", "-t", vaultRevision], "Git vault object type")).trim();
115
+ if (objectType !== "tree") {
116
+ throw new FrozenEvaluationSnapshotError(`${vaultRevision} must identify a Git tree, but Git reported ${JSON.stringify(objectType)}.`);
117
+ }
118
+ const status = await gitOutput(runGit, repository, [
119
+ "status",
120
+ "--porcelain=v1",
121
+ "--untracked-files=all",
122
+ "--",
123
+ options.corpus.frozen.vaultRoot
124
+ ], "Git vault status");
125
+ if (status.trim() !== "") {
126
+ const firstChange = status.trim().split(/\r?\n/u)[0] ?? "unknown vault change";
127
+ throw new FrozenEvaluationSnapshotError(`The frozen evaluation vault has tracked or untracked changes: ${firstChange}.`);
128
+ }
129
+ return Object.freeze({
130
+ repository,
131
+ root,
132
+ vaultRoot: options.corpus.frozen.vaultRoot,
133
+ repositoryCommit: head,
134
+ vaultTree
135
+ });
136
+ }
137
+ function elapsed(startedAt, now) {
138
+ const duration = now() - startedAt;
139
+ return Number.isFinite(duration) && duration > 0 ? duration : 0;
140
+ }
141
+ function utf8Prefix(value, maximumBytes) {
142
+ let bytes = 0;
143
+ let end = 0;
144
+ for (const character of value) {
145
+ const width = Buffer.byteLength(character, "utf8");
146
+ if (bytes + width > maximumBytes)
147
+ break;
148
+ bytes += width;
149
+ end += character.length;
150
+ }
151
+ return value.slice(0, end);
152
+ }
153
+ function diagnosticMessage(parts) {
154
+ const joined = redactEvaluationMachinePaths(parts.join(" ").normalize("NFC").replace(/[\0\r\n]+/gu, " ").trim());
155
+ if (joined === "")
156
+ return;
157
+ return utf8Prefix(joined, DIAGNOSTIC_MESSAGE_BYTES);
158
+ }
159
+ function evidenceSnapshot(value) {
160
+ const serialized = JSON.stringify(value, (_key, candidate) => typeof candidate === "string" ? redactEvaluationMachinePaths(candidate) : candidate);
161
+ if (serialized === undefined)
162
+ return null;
163
+ const bytes = Buffer.byteLength(serialized, "utf8");
164
+ if (bytes <= MAX_EVALUATION_EVIDENCE_BYTES) {
165
+ return JSON.parse(serialized);
166
+ }
167
+ let prefixBytes = MAX_EVALUATION_EVIDENCE_BYTES - 1024;
168
+ while (prefixBytes > 0) {
169
+ const snapshot = {
170
+ truncated: true,
171
+ originalUtf8Bytes: bytes,
172
+ jsonPrefix: utf8Prefix(serialized, prefixBytes)
173
+ };
174
+ if (Buffer.byteLength(JSON.stringify(snapshot), "utf8") <= MAX_EVALUATION_EVIDENCE_BYTES) {
175
+ return snapshot;
176
+ }
177
+ prefixBytes = Math.floor(prefixBytes * 0.75);
178
+ }
179
+ return { truncated: true, originalUtf8Bytes: bytes, jsonPrefix: "" };
180
+ }
181
+ function unavailable(id, requiredInput, noteCount) {
182
+ return Object.freeze({
183
+ status: "unavailable",
184
+ hits: Object.freeze([]),
185
+ diagnostics: Object.freeze([Object.freeze({
186
+ lane: id,
187
+ status: "unavailable",
188
+ message: `${id} retrieval requires ${requiredInput}.`
189
+ })]),
190
+ timings: Object.freeze({}),
191
+ resources: Object.freeze({ noteCount })
192
+ });
193
+ }
194
+ function textHitProvenance(hit) {
195
+ const exactEvidence = hit.evidence.find((evidence) => evidence.kind === "exact");
196
+ const qmdEvidence = hit.evidence.filter((evidence) => evidence.kind === "qmd");
197
+ const explicitLocators = hit.evidence.flatMap((evidence) => evidence.kind !== "exact" ? [] : evidence.matches.flatMap((match) => {
198
+ if (match.field === "title") {
199
+ return [Object.freeze({ kind: "title", title: hit.title })];
200
+ }
201
+ if (match.field === "alias") {
202
+ return [Object.freeze({
203
+ kind: "frontmatter-field-any",
204
+ fields: Object.freeze(["aliases", "alias"])
205
+ })];
206
+ }
207
+ if (match.field === "tag") {
208
+ return [Object.freeze({ kind: "frontmatter-field", field: "tags" })];
209
+ }
210
+ if (match.field === "metadata") {
211
+ return [Object.freeze({ kind: "frontmatter-value", value: match.value })];
212
+ }
213
+ if (match.field === "path") {
214
+ return [Object.freeze({ kind: "source-path", sourcePath: hit.path })];
215
+ }
216
+ return [];
217
+ }));
218
+ const exactContentLocators = hit.line !== undefined && exactEvidence?.matches.some(({ field }) => field === "content") === true && (exactEvidence.identity || qmdEvidence.length === 0) ? [Object.freeze({ kind: "line", line: hit.line })] : [];
219
+ const sameDocumentLocators = [...explicitLocators, ...exactContentLocators];
220
+ const sameDocument = sameDocumentLocators.map((locator) => Object.freeze({
221
+ targetDocumentId: hit.id,
222
+ evidenceDocumentId: hit.id,
223
+ sourcePath: hit.path,
224
+ locator
225
+ }));
226
+ const qmd = qmdEvidence.flatMap((evidence) => evidence.line === undefined || evidence.path === undefined ? [] : [Object.freeze({
227
+ targetDocumentId: hit.id,
228
+ evidenceDocumentId: hit.id,
229
+ sourcePath: evidence.path,
230
+ locator: Object.freeze({ kind: "line", line: evidence.line })
231
+ })]);
232
+ const unique = [...new Map([...sameDocument, ...qmd].map((provenance) => [JSON.stringify(provenance), provenance])).values()];
233
+ return Object.freeze(unique);
234
+ }
235
+ function statusFromDiagnostics(diagnostics, hits) {
236
+ if (hits.length === 0 && diagnostics.length > 0 && diagnostics.every(({ status }) => status === "unavailable"))
237
+ return "unavailable";
238
+ return diagnostics.some(({ status }) => status !== "ready") ? "degraded" : "ready";
239
+ }
240
+ function textResult(result) {
241
+ const hits = Object.freeze(result.results.map((hit) => {
242
+ const provenance = textHitProvenance(hit);
243
+ return Object.freeze({
244
+ documentId: hit.id,
245
+ rank: hit.rank,
246
+ score: hit.score,
247
+ evidence: evidenceSnapshot({
248
+ mode: result.mode,
249
+ path: hit.path,
250
+ title: hit.title,
251
+ identity: hit.identity,
252
+ ...hit.line === undefined ? {} : { line: hit.line },
253
+ snippet: hit.snippet,
254
+ evidence: hit.evidence,
255
+ contributions: hit.contributions,
256
+ ...provenance.length === 0 ? {} : { provenance }
257
+ })
258
+ });
259
+ }));
260
+ const diagnostics = Object.freeze(result.diagnostics.lanes.map((lane) => Object.freeze({
261
+ lane: lane.lane,
262
+ status: lane.status,
263
+ ...lane.message === undefined ? {} : { message: diagnosticMessage([lane.message]) ?? "Search diagnostic unavailable." }
264
+ })));
265
+ const laneResults = new Map(result.diagnostics.lanes.map(({ lane, results }) => [lane, results]));
266
+ return Object.freeze({
267
+ status: statusFromDiagnostics(diagnostics, hits),
268
+ hits,
269
+ diagnostics,
270
+ timings: Object.freeze({ searchMs: result.diagnostics.elapsedMs }),
271
+ resources: Object.freeze({
272
+ noteCount: result.diagnostics.notes,
273
+ resultCount: result.results.length,
274
+ partial: Number(result.partial),
275
+ exactResultCount: laneResults.get("exact") ?? 0,
276
+ qmdResultCount: laneResults.get("qmd") ?? 0,
277
+ ...result.diagnostics.queryEmbedding == null ? {} : {
278
+ queryEmbeddingCalls: result.diagnostics.queryEmbedding.calls,
279
+ queryEmbeddingInputTokens: result.diagnostics.queryEmbedding.inputTokens,
280
+ queryEmbeddingDurationMs: result.diagnostics.queryEmbedding.durationMs
281
+ }
282
+ })
283
+ });
284
+ }
285
+ function stableHits(candidates, limit) {
286
+ const unique = new Map;
287
+ for (const candidate of candidates) {
288
+ if (!unique.has(candidate.documentId))
289
+ unique.set(candidate.documentId, candidate);
290
+ }
291
+ return Object.freeze([...unique.values()].slice(0, limit).map((candidate, index) => Object.freeze({
292
+ documentId: candidate.documentId,
293
+ rank: index + 1,
294
+ ...candidate.score === undefined ? {} : { score: candidate.score },
295
+ evidence: evidenceSnapshot(candidate.evidence)
296
+ })));
297
+ }
298
+ function metadataRetriever(session, now) {
299
+ return Object.freeze({
300
+ id: "metadata",
301
+ retrieve: ({ query, limit, signal }) => {
302
+ if (query.inputs.metadata === undefined) {
303
+ return Promise.resolve(unavailable("metadata", "query.inputs.metadata", session.noteCount));
304
+ }
305
+ throwIfAborted(signal);
306
+ const startedAt = now();
307
+ const rows = session.list({
308
+ filters: query.inputs.metadata.filters,
309
+ tags: query.inputs.metadata.tags,
310
+ limit
311
+ });
312
+ throwIfAborted(signal);
313
+ const provenanceFields = [
314
+ ...query.inputs.metadata.filters.map(({ path }) => path.split(".")[0]),
315
+ ...query.inputs.metadata.tags.length === 0 ? [] : ["tags"]
316
+ ].filter((field) => field !== undefined && field !== "");
317
+ const provenanceFieldList = [...new Set(provenanceFields)];
318
+ const hits = Object.freeze(rows.map((row, index) => Object.freeze({
319
+ documentId: row.id,
320
+ rank: index + 1,
321
+ evidence: evidenceSnapshot({
322
+ ...row,
323
+ ...provenanceFieldList.length === 0 ? {} : {
324
+ provenance: provenanceFieldList.map((field) => ({
325
+ targetDocumentId: row.id,
326
+ evidenceDocumentId: row.id,
327
+ sourcePath: row.path,
328
+ locator: { kind: "frontmatter-field", field }
329
+ }))
330
+ }
331
+ })
332
+ })));
333
+ return Promise.resolve(Object.freeze({
334
+ status: "ready",
335
+ hits,
336
+ diagnostics: Object.freeze([Object.freeze({
337
+ lane: "metadata",
338
+ status: "ready"
339
+ })]),
340
+ timings: Object.freeze({ listMs: elapsed(startedAt, now) }),
341
+ resources: Object.freeze({ noteCount: session.noteCount, resultCount: rows.length })
342
+ }));
343
+ }
344
+ });
345
+ }
346
+ function graphRetriever(session, now) {
347
+ return Object.freeze({
348
+ id: "graph",
349
+ retrieve: ({ query, limit, signal }) => {
350
+ const input = query.inputs.graph;
351
+ if (input === undefined) {
352
+ return Promise.resolve(unavailable("graph", "query.inputs.graph", session.noteCount));
353
+ }
354
+ throwIfAborted(signal);
355
+ const startedAt = now();
356
+ const matches = new Map;
357
+ const diagnostics = [];
358
+ let edges = 0;
359
+ let relations = 0;
360
+ for (const [seedIndex, seed] of input.seeds.entries()) {
361
+ const neighborhood = session.links(seed, {
362
+ direction: "both",
363
+ depth: input.depth,
364
+ limit
365
+ });
366
+ edges += neighborhood.edges.length;
367
+ relations += neighborhood.relations.length;
368
+ diagnostics.push(Object.freeze({
369
+ lane: "graph",
370
+ status: neighborhood.truncated ? "degraded" : "ready",
371
+ ...neighborhood.truncated ? { message: `Graph traversal from ${JSON.stringify(seed)} reached its result limit.` } : {}
372
+ }));
373
+ const nodeIdByPath = new Map(neighborhood.nodes.map((node) => [node.path, node.id]));
374
+ for (const [nodeIndex, node] of neighborhood.nodes.entries()) {
375
+ const links = neighborhood.edges.filter((edge) => edge.source === node.path || edge.target === node.path);
376
+ const authoredRelations = neighborhood.relations.filter((relation) => relation.source === node.id || relation.target === node.id);
377
+ const connections = Object.freeze([
378
+ ...links.map((edge) => Object.freeze({ kind: "link", edge })),
379
+ ...authoredRelations.map((relation) => Object.freeze({
380
+ kind: "relation",
381
+ relation
382
+ }))
383
+ ]);
384
+ const provenance = Object.freeze([...new Map([
385
+ ...links.flatMap((link) => {
386
+ const evidenceDocumentId = nodeIdByPath.get(link.source);
387
+ return evidenceDocumentId === undefined ? [] : [Object.freeze({
388
+ targetDocumentId: node.id,
389
+ evidenceDocumentId,
390
+ sourcePath: link.source,
391
+ locator: Object.freeze({ kind: "line", line: link.line })
392
+ })];
393
+ }),
394
+ ...authoredRelations.map((relation) => Object.freeze({
395
+ targetDocumentId: node.id,
396
+ evidenceDocumentId: relation.source,
397
+ sourcePath: relation.provenance.source,
398
+ locator: Object.freeze({
399
+ kind: "line",
400
+ line: relation.provenance.line
401
+ })
402
+ }))
403
+ ].map((candidate) => [JSON.stringify(candidate), candidate])).values()]);
404
+ const raw = Object.freeze({
405
+ seed,
406
+ node,
407
+ connections,
408
+ ...provenance.length === 0 ? {} : { provenance }
409
+ });
410
+ const existing = matches.get(node.id);
411
+ if (existing === undefined) {
412
+ matches.set(node.id, {
413
+ documentId: node.id,
414
+ distance: node.distance,
415
+ seedIndex,
416
+ nodeIndex,
417
+ evidence: [raw]
418
+ });
419
+ } else {
420
+ existing.evidence.push(raw);
421
+ }
422
+ }
423
+ }
424
+ const candidates = [...matches.values()].toSorted((left, right) => left.distance - right.distance || left.seedIndex - right.seedIndex || left.nodeIndex - right.nodeIndex || left.documentId.localeCompare(right.documentId));
425
+ const hits = stableHits(candidates.map((candidate) => ({
426
+ documentId: candidate.documentId,
427
+ score: 1 / (candidate.distance + 1),
428
+ evidence: {
429
+ neighborhoods: candidate.evidence,
430
+ ...(() => {
431
+ const provenance = [...new Map(candidate.evidence.flatMap((entry) => entry.provenance ?? []).map((entry) => [JSON.stringify(entry), entry])).values()];
432
+ return provenance.length === 0 ? {} : { provenance: Object.freeze(provenance) };
433
+ })()
434
+ }
435
+ })), limit);
436
+ throwIfAborted(signal);
437
+ return Promise.resolve(Object.freeze({
438
+ status: statusFromDiagnostics(diagnostics, hits),
439
+ hits,
440
+ diagnostics: Object.freeze(diagnostics),
441
+ timings: Object.freeze({ linksMs: elapsed(startedAt, now) }),
442
+ resources: Object.freeze({
443
+ noteCount: session.noteCount,
444
+ seedCount: input.seeds.length,
445
+ resultCount: hits.length,
446
+ edgeCount: edges,
447
+ relationCount: relations
448
+ })
449
+ }));
450
+ }
451
+ });
452
+ }
453
+ function pathContextDiagnostics(inspection, memory) {
454
+ const inspectionMessage = diagnosticMessage(inspection.issues.map(({ message }) => message));
455
+ const memoryMessages = [
456
+ ...memory.invalidRecords.details.flatMap(({ issues }) => issues),
457
+ ...memory.advisories.details.map(({ message }) => message),
458
+ ...repositoryMemoryGroupKeys.some((key) => memory.groups[key].truncated) ? ["Repository-memory results were truncated by the evaluation limit."] : []
459
+ ];
460
+ const memoryMessage = diagnosticMessage(memoryMessages);
461
+ return Object.freeze([
462
+ Object.freeze({
463
+ lane: "agent-context",
464
+ status: inspection.issues.length === 0 ? "ready" : "degraded",
465
+ ...inspectionMessage === undefined ? {} : { message: inspectionMessage }
466
+ }),
467
+ Object.freeze({
468
+ lane: "repository-memory",
469
+ status: memoryMessages.length === 0 ? "ready" : "degraded",
470
+ ...memoryMessage === undefined ? {} : { message: memoryMessage }
471
+ })
472
+ ]);
473
+ }
474
+ function pathContextRetriever(session, snapshot, repository, inspectContext, buildMemory, now) {
475
+ return Object.freeze({
476
+ id: "path-context",
477
+ retrieve: async ({ query, limit, signal }) => {
478
+ const input = query.inputs.context;
479
+ if (input === undefined) {
480
+ return unavailable("path-context", "query.inputs.context", session.noteCount);
481
+ }
482
+ throwIfAborted(signal);
483
+ const inspectionStartedAt = now();
484
+ const inspection = await inspectContext(snapshot.notes, {
485
+ repositoryRoot: repository,
486
+ target: input.repositoryPath,
487
+ targetKind: "auto"
488
+ });
489
+ const inspectionMs = elapsed(inspectionStartedAt, now);
490
+ throwIfAborted(signal);
491
+ const memoryStartedAt = now();
492
+ const memory = await buildMemory(snapshot.notes, {
493
+ repositoryRoot: repository,
494
+ target: input.repositoryPath,
495
+ groupLimit: Math.min(limit, MAX_REPOSITORY_MEMORY_GROUP_LIMIT),
496
+ detailLimit: Math.min(limit, MAX_REPOSITORY_MEMORY_DETAIL_LIMIT)
497
+ });
498
+ const memoryMs = elapsed(memoryStartedAt, now);
499
+ throwIfAborted(signal);
500
+ const candidates = [
501
+ ...inspection.matchingContexts.map((hub) => ({
502
+ documentId: hub.note.id,
503
+ evidence: {
504
+ kind: "agent-context",
505
+ path: hub.note.path,
506
+ rawScope: hub.rawScope,
507
+ scope: hub.scope,
508
+ canonicalId: hub.canonicalId,
509
+ canonicalPath: hub.canonicalPath,
510
+ guidePath: hub.guidePath,
511
+ canonical: hub.canonical,
512
+ reciprocal: hub.reciprocal,
513
+ valid: hub.valid,
514
+ provenance: [{
515
+ targetDocumentId: hub.note.id,
516
+ evidenceDocumentId: hub.note.id,
517
+ sourcePath: hub.note.path,
518
+ locator: { kind: "frontmatter-field", field: "scope" }
519
+ }]
520
+ }
521
+ })),
522
+ ...repositoryMemoryGroupKeys.flatMap((group) => memory.groups[group].records.map((record) => ({
523
+ documentId: record.id,
524
+ evidence: {
525
+ kind: "repository-memory",
526
+ group,
527
+ record,
528
+ provenance: [{
529
+ targetDocumentId: record.id,
530
+ evidenceDocumentId: record.id,
531
+ sourcePath: record.path,
532
+ locator: { kind: "frontmatter-field", field: "repository_scopes" }
533
+ }]
534
+ }
535
+ })))
536
+ ];
537
+ const hits = stableHits(candidates, limit);
538
+ const diagnostics = pathContextDiagnostics(inspection, memory);
539
+ return Object.freeze({
540
+ status: statusFromDiagnostics(diagnostics, hits),
541
+ hits,
542
+ diagnostics,
543
+ timings: Object.freeze({ inspectionMs, memoryMs }),
544
+ resources: Object.freeze({
545
+ noteCount: session.noteCount,
546
+ resultCount: hits.length,
547
+ matchingContextCount: inspection.matchingContexts.length,
548
+ inheritedGuideCount: inspection.inheritedGuides.length,
549
+ contextIssueCount: inspection.issues.length,
550
+ memoryMatchedCount: memory.counts.matched,
551
+ memoryReturnedCount: memory.counts.returned,
552
+ memoryInvalidCount: memory.counts.invalid,
553
+ memoryAdvisoryCount: memory.counts.advisories
554
+ })
555
+ });
556
+ }
557
+ });
558
+ }
559
+ function gitDiagnostic(lane, result) {
560
+ if (result.status === "unavailable") {
561
+ return Object.freeze({
562
+ lane,
563
+ status: "unavailable",
564
+ message: diagnosticMessage([result.reason]) ?? "Git retrieval is unavailable."
565
+ });
566
+ }
567
+ const limited = result.limitedCommits ?? [];
568
+ return Object.freeze({
569
+ lane,
570
+ status: limited.length === 0 ? "ready" : "degraded",
571
+ ...limited.length === 0 ? {} : { message: `${limited.length} oversized Git commit record(s) have limited evidence.` }
572
+ });
573
+ }
574
+ function gitRetriever(session, frozenCommit, now) {
575
+ return Object.freeze({
576
+ id: "git",
577
+ retrieve: async ({ query, limit, signal }) => {
578
+ const input = query.inputs.history;
579
+ if (input === undefined) {
580
+ return unavailable("git", "query.inputs.history", session.noteCount);
581
+ }
582
+ throwIfAborted(signal);
583
+ const searchStartedAt = now();
584
+ const searched = await session.searchHistory({
585
+ query: input.query,
586
+ limit: Math.min(limit, 100)
587
+ });
588
+ const searchMs = elapsed(searchStartedAt, now);
589
+ throwIfAborted(signal);
590
+ const historyStartedAt = now();
591
+ const history = await session.history(input.noteIds);
592
+ const historyMs = elapsed(historyStartedAt, now);
593
+ throwIfAborted(signal);
594
+ for (const result of [searched, history]) {
595
+ if (result.status === "ready" && result.head !== frozenCommit) {
596
+ throw new FrozenEvaluationSnapshotError(`Git retrieval observed HEAD ${result.head}, expected frozen commit ${frozenCommit}.`);
597
+ }
598
+ }
599
+ const searchedById = new Map(searched.status === "ready" ? searched.hits.map((hit) => [hit.id, hit]) : []);
600
+ const historyById = new Map(history.status === "ready" ? history.notes.map((note) => [note.id, note]) : []);
601
+ const orderedIds = [
602
+ ...input.noteIds.filter((id) => historyById.has(id)),
603
+ ...searched.status === "ready" ? searched.hits.map(({ id }) => id) : []
604
+ ];
605
+ const candidates = orderedIds.map((documentId) => {
606
+ const searchedHit = searchedById.get(documentId);
607
+ const provenance = historyById.get(documentId);
608
+ return {
609
+ documentId,
610
+ ...searchedHit === undefined ? {} : { score: searchedHit.score },
611
+ evidence: {
612
+ ...provenance === undefined ? {} : { history: provenance },
613
+ ...searchedHit === undefined ? {} : { search: searchedHit }
614
+ }
615
+ };
616
+ });
617
+ const hits = stableHits(candidates, limit);
618
+ const diagnostics = Object.freeze([
619
+ gitDiagnostic("git-search", searched),
620
+ gitDiagnostic("git-history", history)
621
+ ]);
622
+ const searchedLimited = searched.status === "ready" ? searched.limitedCommits?.length ?? 0 : 0;
623
+ const historyLimited = history.status === "ready" ? history.limitedCommits?.length ?? 0 : 0;
624
+ return Object.freeze({
625
+ status: statusFromDiagnostics(diagnostics, hits),
626
+ hits,
627
+ diagnostics,
628
+ timings: Object.freeze({ searchHistoryMs: searchMs, historyMs }),
629
+ resources: Object.freeze({
630
+ noteCount: session.noteCount,
631
+ resultCount: hits.length,
632
+ searchResultCount: searched.status === "ready" ? searched.hits.length : 0,
633
+ historyResultCount: history.status === "ready" ? history.notes.length : 0,
634
+ limitedCommitCount: searchedLimited + historyLimited
635
+ })
636
+ });
637
+ }
638
+ });
639
+ }
640
+ function throwIfAborted(signal) {
641
+ if (!signal.aborted)
642
+ return;
643
+ if (signal.reason instanceof Error)
644
+ throw signal.reason;
645
+ throw new Error("Knowledge-base evaluation retrieval was aborted.");
646
+ }
647
+ function textRetriever(id, session) {
648
+ return Object.freeze({
649
+ id,
650
+ retrieve: async ({ query, limit, signal }) => {
651
+ const text = query.inputs.text;
652
+ if (text === undefined)
653
+ return unavailable(id, "query.inputs.text", session.noteCount);
654
+ throwIfAborted(signal);
655
+ const result = await session.search({
656
+ query: text,
657
+ mode: id,
658
+ limit: Math.min(limit, MAX_SEARCH_RESULTS),
659
+ graph: false,
660
+ history: false
661
+ });
662
+ throwIfAborted(signal);
663
+ return textResult(result);
664
+ }
665
+ });
666
+ }
667
+ function knowledgeBaseDependencies(options, snapshot) {
668
+ const git = options.git === undefined && options.runGit === undefined ? undefined : {
669
+ ...options.git,
670
+ ...options.git?.runGit !== undefined || options.runGit === undefined ? {} : { runGit: options.runGit }
671
+ };
672
+ return {
673
+ scanVault: () => Promise.resolve(snapshot),
674
+ ...options.semantic === undefined ? {} : { semantic: options.semantic },
675
+ ...options.openSemanticSearchSession === undefined ? {} : { openSemanticSearchSession: options.openSemanticSearchSession },
676
+ ...git === undefined ? {} : { git },
677
+ ...options.indexGitHistory === undefined ? {} : { indexGitHistory: options.indexGitHistory }
678
+ };
679
+ }
680
+ async function openKnowledgeBaseEvaluation(options) {
681
+ const verified = await verifyFrozenEvaluationSnapshot(options);
682
+ const scanner = options.scanVault ?? scanVault;
683
+ const snapshot = await scanner(verified.root, { mentionScope: false });
684
+ const open = options.openKnowledgeBase ?? openKnowledgeBase;
685
+ const session = await open({
686
+ root: verified.root,
687
+ repository: verified.repository,
688
+ ...options.database === undefined ? {} : { database: options.database },
689
+ ...options.embeddingModelFile === undefined ? {} : { embeddingModelFile: options.embeddingModelFile },
690
+ ...options.embeddingModelLease === undefined ? {} : { embeddingModelLease: options.embeddingModelLease },
691
+ ...options.requireStoreLocalVectorBoundary === undefined ? {} : {
692
+ requireStoreLocalVectorBoundary: options.requireStoreLocalVectorBoundary
693
+ }
694
+ }, knowledgeBaseDependencies(options, snapshot));
695
+ const now = options.now ?? performance.now.bind(performance);
696
+ const inspectContext = options.inspectAgentContextRepository ?? inspectAgentContextRepository;
697
+ const buildMemory = options.buildRepositoryMemoryContext ?? buildRepositoryMemoryContext;
698
+ const retrievers = Object.freeze([
699
+ textRetriever("exact", session),
700
+ textRetriever("keyword", session),
701
+ textRetriever("semantic", session),
702
+ textRetriever("hybrid", session),
703
+ metadataRetriever(session, now),
704
+ graphRetriever(session, now),
705
+ pathContextRetriever(session, snapshot, verified.repository, inspectContext, buildMemory, now),
706
+ gitRetriever(session, verified.repositoryCommit, now)
707
+ ]);
708
+ return Object.freeze({ retrievers, close: session.close });
709
+ }
710
+
711
+ export { knowledgeBaseEvaluationRetrieverIds, FrozenEvaluationSnapshotError, verifyFrozenEvaluationSnapshot, openKnowledgeBaseEvaluation };