From a7c17fb998a64b1230de3d56cfe80ba83140ee55 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 08:36:35 +0000 Subject: [PATCH 1/4] Initial plan From eefe91be146fd1346d9e3c7a8e743f02fd1efa48 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 08:41:09 +0000 Subject: [PATCH 2/4] Apply review feedback: sort results, JSDoc, TODO comment, stub formatting, add missing tests Co-authored-by: devlux76 <86517969+devlux76@users.noreply.github.com> --- cortex/Query.ts | 5 ++ storage/IndexedDbMetadataStore.ts | 5 +- tests/SalienceEngine.test.ts | 4 +- tests/cortex/Query.test.ts | 96 ++++++++++++++++++++++++++++++- 4 files changed, 107 insertions(+), 3 deletions(-) diff --git a/cortex/Query.ts b/cortex/Query.ts index deda5b8..b6a1427 100644 --- a/cortex/Query.ts +++ b/cortex/Query.ts @@ -23,6 +23,10 @@ function dot(a: Float32Array, b: Float32Array): number { return sum; } +/** + * Concatenates an array of equal-length vectors into a single flat buffer. + * @param vectors - Must be non-empty; every element must have the same length. + */ function concatVectors(vectors: Float32Array[]): Float32Array { const dim = vectors[0].length; const out = new Float32Array(vectors.length * dim); @@ -128,6 +132,7 @@ export async function query( } const combined = [...hotpathResults, ...coldResults]; + combined.sort((a, b) => b.score - a.score); // Update activity for returned pages await Promise.all(combined.map(async ({ page }) => { diff --git a/storage/IndexedDbMetadataStore.ts b/storage/IndexedDbMetadataStore.ts index 8013db8..2dcee63 100644 --- a/storage/IndexedDbMetadataStore.ts +++ b/storage/IndexedDbMetadataStore.ts @@ -145,7 +145,10 @@ export class IndexedDbMetadataStore implements MetadataStore { return this._get(STORE.pages, pageId); } - /** Returns all pages in the store. Used for warm/cold fallbacks in query. */ + /** Returns all pages in the store. Used for warm/cold fallbacks in query. + * TODO: Replace with a paginated or indexed scan before production use — + * loading every page into memory is expensive for large corpora. + */ async getAllPages(): Promise { return new Promise((resolve, reject) => { const tx = this.db.transaction(STORE.pages, "readonly"); diff --git a/tests/SalienceEngine.test.ts b/tests/SalienceEngine.test.ts index ecb6785..0618a33 100644 --- a/tests/SalienceEngine.test.ts +++ b/tests/SalienceEngine.test.ts @@ -104,7 +104,9 @@ class MockMetadataStore implements MetadataStore { // --- Stubs for unused MetadataStore methods --- async putPage(): Promise { /* stub */ } - async getPage(): Promise { return undefined; } async getAllPages(): Promise { return []; } async putBook(): Promise { /* stub */ } + async getPage(): Promise { return undefined; } + async getAllPages(): Promise { return []; } + async putBook(): Promise { /* stub */ } async getBook(): Promise { return undefined; } async putVolume(): Promise { /* stub */ } async getVolume(): Promise { return undefined; } diff --git a/tests/cortex/Query.test.ts b/tests/cortex/Query.test.ts index 51b33d8..bb0690d 100644 --- a/tests/cortex/Query.test.ts +++ b/tests/cortex/Query.test.ts @@ -13,7 +13,7 @@ import type { ModelProfile } from "../../core/ModelProfile"; import type { VectorBackend } from "../../VectorBackend"; class TestVectorBackend implements VectorBackend { - readonly kind = "test" as const; + readonly kind = "wasm" as const; async dotMany( query: Float32Array, @@ -61,6 +61,44 @@ describe("cortex query (minimal)", () => { (globalThis as any).IDBKeyRange = FakeIDBKeyRange; }); + it("returns empty results for an empty corpus", async () => { + const metadataStore = await IndexedDbMetadataStore.open(freshDbName()); + const vectorStore = new MemoryVectorStore(); + + const backend = new DeterministicDummyEmbeddingBackend({ dimension: 4 }); + const vectorBackend = new TestVectorBackend(); + + const runner = new EmbeddingRunner(async () => ({ + backend, + selectedKind: "dummy" as const, + reason: "forced" as const, + supportedKinds: ["dummy" as const], + measurements: [], + })); + + const profile: ModelProfile = { + modelId: "test-model", + embeddingDimension: 4, + contextWindowTokens: 64, + truncationTokens: 48, + maxChunkTokens: 5, + source: "metadata", + }; + + const result = await query("anything", { + modelProfile: profile, + embeddingRunner: runner, + vectorStore, + metadataStore, + vectorBackend, + topK: 5, + }); + + expect(result.pages).toHaveLength(0); + expect(result.scores).toHaveLength(0); + expect(result.metadata.returned).toBe(0); + }); + it("returns the most relevant page and updates activity", async () => { const metadataStore = await IndexedDbMetadataStore.open(freshDbName()); const vectorStore = new MemoryVectorStore(); @@ -120,4 +158,60 @@ describe("cortex query (minimal)", () => { expect(activity?.queryHitCount).toBe(1); expect(activity?.lastQueryAt).toBeDefined(); }); + + it("returns results in descending score order (relevance)", async () => { + const metadataStore = await IndexedDbMetadataStore.open(freshDbName()); + const vectorStore = new MemoryVectorStore(); + const keyPair = await generateKeyPair(); + + const backend = new DeterministicDummyEmbeddingBackend({ dimension: 4 }); + const vectorBackend = new TestVectorBackend(); + + const runner = new EmbeddingRunner(async () => ({ + backend, + selectedKind: "dummy" as const, + reason: "forced" as const, + supportedKinds: ["dummy" as const], + measurements: [], + })); + + const profile: ModelProfile = { + modelId: "test-model", + embeddingDimension: 4, + contextWindowTokens: 64, + truncationTokens: 48, + maxChunkTokens: 5, + source: "metadata", + }; + + const text = "One two three four five six seven eight nine ten."; + const ingestResult = await ingestText(text, { + modelProfile: profile, + embeddingRunner: runner, + vectorStore, + metadataStore, + keyPair, + }); + + expect(ingestResult.pages.length).toBeGreaterThanOrEqual(2); + + const targetPage = ingestResult.pages[0]; + + const result = await query(targetPage.content, { + modelProfile: profile, + embeddingRunner: runner, + vectorStore, + metadataStore, + vectorBackend, + topK: ingestResult.pages.length, + }); + + // Results must include the page whose content matches the query. + expect(result.pages.map((p) => p.pageId)).toContain(targetPage.pageId); + + // Scores must be in non-increasing order. + for (let i = 1; i < result.scores.length; i++) { + expect(result.scores[i]).toBeLessThanOrEqual(result.scores[i - 1]); + } + }); }); From f842b7f2cfbf9d1b7df9461104809b8d8c283571 Mon Sep 17 00:00:00 2001 From: "S. Dale Morrey" <86517969+devlux76@users.noreply.github.com> Date: Fri, 13 Mar 2026 02:57:03 -0600 Subject: [PATCH 3/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- tests/cortex/Query.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cortex/Query.test.ts b/tests/cortex/Query.test.ts index 3befb1d..b189b8f 100644 --- a/tests/cortex/Query.test.ts +++ b/tests/cortex/Query.test.ts @@ -14,7 +14,6 @@ import type { ModelProfile } from "../../core/ModelProfile"; import type { VectorBackend } from "../../VectorBackend"; class TestVectorBackend implements VectorBackend { - readonly kind = "wasm" as const; readonly kind: BackendKind = "wasm"; async dotMany( From 1640537963923b4c34fedbd4e0aac6e0aaa5fafe Mon Sep 17 00:00:00 2001 From: "S. Dale Morrey" <86517969+devlux76@users.noreply.github.com> Date: Fri, 13 Mar 2026 02:57:35 -0600 Subject: [PATCH 4/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- storage/IndexedDbMetadataStore.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/IndexedDbMetadataStore.ts b/storage/IndexedDbMetadataStore.ts index 2dcee63..8cd21e0 100644 --- a/storage/IndexedDbMetadataStore.ts +++ b/storage/IndexedDbMetadataStore.ts @@ -145,7 +145,8 @@ export class IndexedDbMetadataStore implements MetadataStore { return this._get(STORE.pages, pageId); } - /** Returns all pages in the store. Used for warm/cold fallbacks in query. + /** + * Returns all pages in the store. Used for warm/cold fallbacks in query. * TODO: Replace with a paginated or indexed scan before production use — * loading every page into memory is expensive for large corpora. */