Context
Depends on #66 (RAG-1). Part of the v2 RAG milestone.
What
Implement a lightweight BM25 scorer (~80 lines, no external deps) over data/live-docs.json.
File: src/agent/docs-index.ts
Export:
```ts
/** Returns the top-k most relevant chunks for a query. Returns [] if index is absent. */
export function retrieveLiveDocs(query: string, topK?: number): DocChunk[];
/** True if the local docs index is older than maxAgeDays (default 30). */
export function isDocIndexStale(maxAgeDays?: number): boolean;
```
Implementation notes:
- Tokenise query and corpus: lowercase, split on word boundaries, strip punctuation
- BM25 with standard defaults: k1=1.5, b=0.75
- Return top
topK (default 3) chunks above a minimum relevance threshold
- If
data/live-docs.json is absent, return [] silently — never throw
Tests in src/agent/docs-index.test.ts:
- Returns correct top result for known device queries ("Operator FM", "Glue Compressor ratio")
- Returns
[] when data file is absent
- Respects
topK limit
isDocIndexStale returns true for an index older than the threshold
Acceptance criteria
Context
Depends on #66 (RAG-1). Part of the v2 RAG milestone.
What
Implement a lightweight BM25 scorer (~80 lines, no external deps) over
data/live-docs.json.File:
src/agent/docs-index.tsExport:
```ts
/** Returns the top-k most relevant chunks for a query. Returns [] if index is absent. */
export function retrieveLiveDocs(query: string, topK?: number): DocChunk[];
/** True if the local docs index is older than maxAgeDays (default 30). */
export function isDocIndexStale(maxAgeDays?: number): boolean;
```
Implementation notes:
topK(default 3) chunks above a minimum relevance thresholddata/live-docs.jsonis absent, return[]silently — never throwTests in
src/agent/docs-index.test.ts:[]when data file is absenttopKlimitisDocIndexStalereturns true for an index older than the thresholdAcceptance criteria
retrieveLiveDocs('Operator FM synthesis')returns a chunk mentioning Operator from the manualretrieveLiveDocs('anything')returns[]whendata/live-docs.jsondoes not exist