(
projectRoot: string,
query: string,
opts: { topK?: number; minScore?: number; diversity?: number } = {},
)
| 157 | * Builds a one-shot file-existence Set (each touched file checked once) so the pure ranker |
| 158 | * can ground episodes against the CURRENT tree without doing I/O itself. */ |
| 159 | export async function loadEpisodeBlock( |
| 160 | projectRoot: string, |
| 161 | query: string, |
| 162 | opts: { topK?: number; minScore?: number; diversity?: number } = {}, |
| 163 | ): Promise<string> { |
| 164 | const episodes = await readEpisodes(projectRoot); |
| 165 | // Resolve existence once per distinct file referenced by any episode. |
| 166 | const referenced = new Set<string>(); |
| 167 | for (const e of episodes) for (const f of e.filesChanged) referenced.add(f); |
| 168 | const existing = new Set<string>(); |
| 169 | await Promise.all([...referenced].map(async f => { |
| 170 | try { await fs.access(path.resolve(projectRoot, f)); existing.add(f); } catch { /* gone */ } |
| 171 | })); |
| 172 | return buildEpisodeBlock(rankEpisodes(query, episodes, { ...opts, fileExists: f => existing.has(f) })); |
| 173 | } |
no test coverage detected