Files
waggle-os/packages/hive-mind-core/tests/mind/search-date-window.test.ts
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

131 lines
4.8 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { MindDB } from '../../src/mind/db.js';
import { FrameStore } from '../../src/mind/frames.js';
import { SessionStore } from '../../src/mind/sessions.js';
import { HybridSearch } from '../../src/mind/search.js';
import { MockEmbedder } from './helpers/mock-embedder.js';
/**
* W4.1b — since/until substrate fixes (W4-PRODUCTION-PORT-PLAN-2026-06-11.md
* §3, production bug #2):
*
* FENCEPOST: `created_at` carries mixed formats ("YYYY-MM-DD HH:MM:SS" from
* datetime('now') vs harvest ISO "…T…Z"). A date-only `until` string-compared
* below any same-day timestamp, silently excluding the final day of every
* window. Date-only bounds now compare on the 10-char date prefix.
*
* SLOT CONSUMPTION: the temporal filter ran AFTER the lanes (WHERE over
* candidate ids), so out-of-window candidates consumed lane slots and results
* shrank below `limit` even when in-window frames existed deeper in the
* lanes. Lanes now over-fetch (limit*10) when a window is active.
*/
describe('HybridSearch — since/until date-window fixes (W4.1b)', () => {
let db: MindDB;
let frames: FrameStore;
let sessions: SessionStore;
let search: HybridSearch;
let gopId: string;
beforeEach(() => {
db = new MindDB(':memory:');
frames = new FrameStore(db);
sessions = new SessionStore(db);
search = new HybridSearch(db, new MockEmbedder());
gopId = sessions.create().gop_id;
});
afterEach(() => {
db.close();
});
function setCreatedAt(frameId: number, createdAt: string): void {
db.getDatabase()
.prepare('UPDATE memory_frames SET created_at = ? WHERE id = ?')
.run(createdAt, frameId);
}
describe('fencepost: date-only until includes the whole final day', () => {
it('returns a frame whose ISO timestamp falls later on the until day', async () => {
const f = frames.createIFrame(gopId, 'quarterly metrics review for the launch', 'normal', 'user_stated');
setCreatedAt(f.id, '2026-03-21T10:00:00.000Z'); // same day, after midnight
const hits = await search.search('quarterly metrics review', {
limit: 5,
until: '2026-03-21',
});
expect(hits.map(h => h.frame.id)).toContain(f.id);
});
it('returns a frame with a space-separated timestamp on the until day', async () => {
const f = frames.createIFrame(gopId, 'quarterly metrics review for the launch', 'normal', 'user_stated');
setCreatedAt(f.id, '2026-03-21 14:30:00'); // datetime('now') format
const hits = await search.search('quarterly metrics review', {
limit: 5,
until: '2026-03-21',
});
expect(hits.map(h => h.frame.id)).toContain(f.id);
});
it('still excludes frames after the until day', async () => {
const f = frames.createIFrame(gopId, 'quarterly metrics review for the launch', 'normal', 'user_stated');
setCreatedAt(f.id, '2026-03-22T00:30:00.000Z');
const hits = await search.search('quarterly metrics review', {
limit: 5,
until: '2026-03-21',
});
expect(hits.map(h => h.frame.id)).not.toContain(f.id);
});
it('date-only since includes frames from midnight of that day', async () => {
const f = frames.createIFrame(gopId, 'quarterly metrics review for the launch', 'normal', 'user_stated');
setCreatedAt(f.id, '2026-03-21T00:30:00.000Z');
const hits = await search.search('quarterly metrics review', {
limit: 5,
since: '2026-03-21',
});
expect(hits.map(h => h.frame.id)).toContain(f.id);
});
});
describe('slot consumption: windowed search reaches past out-of-window candidates', () => {
it('returns in-window frames even when out-of-window frames dominate the lanes', async () => {
// 30 out-of-window frames that rank HIGHER on the keyword lane (denser
// keyword repetition) — in the old code these filled the limit*2 lane
// slots and the post-filter left nothing.
for (let i = 0; i < 30; i++) {
const f = frames.createIFrame(
gopId,
`alpha rollout alpha checklist item ${i} alpha`,
'normal',
'user_stated',
);
setCreatedAt(f.id, '2026-06-01T08:00:00.000Z');
}
// 3 in-window frames, weaker keyword density
const inWindow: number[] = [];
for (let i = 0; i < 3; i++) {
const f = frames.createIFrame(
gopId,
`alpha planning note ${i} from spring`,
'normal',
'user_stated',
);
setCreatedAt(f.id, `2025-05-1${i}T09:00:00.000Z`);
inWindow.push(f.id);
}
const hits = await search.search('alpha', {
limit: 5,
since: '2025-05-01',
until: '2025-05-31',
});
const ids = hits.map(h => h.frame.id);
for (const id of inWindow) expect(ids).toContain(id);
});
});
});