From f6d9a83e120834338c81be6d043533291b10a4b2 Mon Sep 17 00:00:00 2001 From: mohammed naji Date: Sun, 6 Sep 2026 18:30:44 +0400 Subject: [PATCH 1/2] fix(retrieve): preserve selected symbol source evidence --- src/runtime/retrieve.ts | 26 ++++- .../unit/retrieve-source-preservation.test.ts | 109 ++++++++++++++++++ 2 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 tests/unit/retrieve-source-preservation.test.ts diff --git a/src/runtime/retrieve.ts b/src/runtime/retrieve.ts index 820b0414..fea3cc1f 100644 --- a/src/runtime/retrieve.ts +++ b/src/runtime/retrieve.ts @@ -1228,7 +1228,31 @@ export function readQueryEvidenceSnippet( } } - const selectedLines = selectQueryEvidenceLines(selectedRange) + let selectedLines = selectQueryEvidenceLines(selectedRange) + if (scope === 'source_file' && !options.fileNodeLike) { + const symbolLine = [...selectQueryEvidenceLines(symbolEvidence)] + .sort((left, right) => right.score - left.score || left.index - right.index)[0] + const symbolSnippet = symbolLine ? renderQueryEvidenceLines([symbolLine]) : null + if (symbolLine && symbolSnippet) { + let mergedLines = [symbolLine] + for (const fileLine of selectedLines) { + if (mergedLines.length >= QUERY_EVIDENCE_SNIPPET_MAX_LINES) { + break + } + if (mergedLines.some((line) => ( + fileLine.index <= line.endIndex && line.index <= fileLine.endIndex + ))) { + continue + } + const candidateLines = [...mergedLines, fileLine] + .sort((left, right) => left.index - right.index) + if (renderQueryEvidenceLines(candidateLines)?.split('\n').includes(symbolSnippet)) { + mergedLines = candidateLines + } + } + selectedLines = mergedLines + } + } const snippet = renderQueryEvidenceLines(selectedLines) if (!snippet || selectedLines.length === 0) { return null diff --git a/tests/unit/retrieve-source-preservation.test.ts b/tests/unit/retrieve-source-preservation.test.ts new file mode 100644 index 00000000..1ef19a9f --- /dev/null +++ b/tests/unit/retrieve-source-preservation.test.ts @@ -0,0 +1,109 @@ +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { join, resolve } from 'node:path' + +import { describe, expect, it } from 'vitest' + +import { readQueryEvidenceSnippet } from '../../src/runtime/retrieve.js' + +const QUESTION = 'How does sanitize input lead to request validation and insertion, then dispatch with retry handling?' + +function createFixture(): { root: string; sourceFile: string } { + const fixtureParent = resolve('out', 'test-runtime') + mkdirSync(fixtureParent, { recursive: true }) + const root = mkdtempSync(join(fixtureParent, 'madar-source-preservation-')) + const sourceFile = join(root, 'processing.ts') + return { root, sourceFile } +} + +describe('query evidence source preservation', () => { + it('keeps complete one-line symbol evidence beside stronger same-file matches', () => { + const { root, sourceFile } = createFixture() + const sourceLines = [ + 'export const foldValue = (value: string) => sanitize(value)', + 'export const wrapValue = (value: string) => sanitize(`[${value}]`)', + '', + 'export async function processRequest(payload: Payload) {', + ' const validationResult = validateRequest(payload)', + ' await insertRecord(validationResult)', + ' await dispatchRecord(validationResult)', + ' return retryDelivery(validationResult)', + '}', + ] + try { + writeFileSync(sourceFile, sourceLines.join('\n'), 'utf8') + + for (const [lineNumber, label] of [[1, 'foldValue'], [2, 'wrapValue']] as const) { + const evidence = readQueryEvidenceSnippet(sourceFile, lineNumber, { + question: QUESTION, + label, + sourceLocation: `L${lineNumber}`, + }) + + expect(evidence).toMatchObject({ scope: 'source_file' }) + expect(evidence?.snippet).toContain(`L${lineNumber}: ${sourceLines[lineNumber - 1]}`) + expect(evidence?.snippet).toContain('dispatchRecord') + } + } finally { + rmSync(root, { recursive: true, force: true }) + } + }) + + it('keeps selected implementation evidence from a short multiline symbol', () => { + const { root, sourceFile } = createFixture() + try { + writeFileSync(sourceFile, [ + 'export function shapeValue(value: string) {', + ' const output = sanitize(value)', + ' return output', + '}', + '', + 'export async function processRequest(payload: Payload) {', + ' const validationResult = validateRequest(payload)', + ' await insertRecord(validationResult)', + ' await dispatchRecord(validationResult)', + ' return retryDelivery(validationResult)', + '}', + ].join('\n'), 'utf8') + + const evidence = readQueryEvidenceSnippet(sourceFile, 1, { + question: QUESTION, + label: 'shapeValue', + sourceLocation: 'L1-L4', + }) + + expect(evidence).toMatchObject({ scope: 'source_file' }) + expect(evidence?.snippet).toContain('L2: const output = sanitize(value)') + expect(evidence?.snippet).toContain('dispatchRecord') + } finally { + rmSync(root, { recursive: true, force: true }) + } + }) + + it('leaves a helper-only split-file excerpt unchanged', () => { + const { root, sourceFile } = createFixture() + const helperLine = 'export const foldValue = (value: string) => sanitize(value)' + try { + writeFileSync(sourceFile, helperLine, 'utf8') + writeFileSync(join(root, 'workflow.ts'), [ + 'const validationResult = validateRequest(payload)', + 'await insertRecord(validationResult)', + 'await dispatchRecord(validationResult)', + 'return retryDelivery(validationResult)', + ].join('\n'), 'utf8') + + const evidence = readQueryEvidenceSnippet(sourceFile, 1, { + question: QUESTION, + label: 'foldValue', + sourceLocation: 'L1', + }) + + expect(evidence).toEqual({ + snippet: `L1: ${helperLine}`, + lineNumber: 1, + scope: 'symbol', + }) + } finally { + rmSync(root, { recursive: true, force: true }) + } + }) +}) From e02dcfa0d8751cdaafe9de6154019c500282e63d Mon Sep 17 00:00:00 2001 From: mohammed naji Date: Sun, 6 Sep 2026 21:25:50 +0400 Subject: [PATCH 2/2] fix(retrieve): retain unscored symbol source with file evidence --- src/runtime/retrieve.ts | 37 ++++- .../unit/retrieve-source-preservation.test.ts | 144 ++++++++++++++++++ 2 files changed, 179 insertions(+), 2 deletions(-) diff --git a/src/runtime/retrieve.ts b/src/runtime/retrieve.ts index fea3cc1f..bdd97d21 100644 --- a/src/runtime/retrieve.ts +++ b/src/runtime/retrieve.ts @@ -1230,8 +1230,41 @@ export function readQueryEvidenceSnippet( let selectedLines = selectQueryEvidenceLines(selectedRange) if (scope === 'source_file' && !options.fileNodeLike) { - const symbolLine = [...selectQueryEvidenceLines(symbolEvidence)] - .sort((left, right) => right.score - left.score || left.index - right.index)[0] + const scoredSymbolLines = [...selectQueryEvidenceLines(symbolEvidence)] + .sort((left, right) => right.score - left.score || left.index - right.index) + let symbolLine = scoredSymbolLines[0] + + if (!symbolLine) { + const fragmentRank = (fragment: QueryEvidenceFragment): number => { + if (QUERY_EVIDENCE_LOW_VALUE_LINE_PATTERN.test(fragment.text)) { + return 3 + } + if (QUERY_EVIDENCE_OPERATION_PATTERN.test(fragment.text)) { + return 0 + } + if (QUERY_EVIDENCE_DECLARATION_PATTERN.test(fragment.text)) { + return 2 + } + return 1 + } + + const symbolFragment = queryEvidenceFragments(lines, symbolRange) + .sort((left, right) => ( + fragmentRank(left) - fragmentRank(right) + || left.index - right.index + ))[0] + if (symbolFragment) { + symbolLine = { + index: symbolFragment.index, + endIndex: symbolFragment.endIndex, + text: symbolFragment.text, + score: 0, + matchedTerms: new Set(), + matchedObligations: new Set(), + identifierTerms: new Set(), + } + } + } const symbolSnippet = symbolLine ? renderQueryEvidenceLines([symbolLine]) : null if (symbolLine && symbolSnippet) { let mergedLines = [symbolLine] diff --git a/tests/unit/retrieve-source-preservation.test.ts b/tests/unit/retrieve-source-preservation.test.ts index 1ef19a9f..e0c0aef7 100644 --- a/tests/unit/retrieve-source-preservation.test.ts +++ b/tests/unit/retrieve-source-preservation.test.ts @@ -79,6 +79,150 @@ describe('query evidence source preservation', () => { } }) + it('keeps neutral helper source before and after stronger file matches', () => { + const { root, sourceFile } = createFixture() + const sourceLines = [ + 'export const combinePair = (left: number, right: number) => left + right', + '', + 'export function keepDatum(datum: T) {', + ' return datum', + '}', + '', + 'export const polishText = (text: string) => text.trim().toUpperCase()', + '', + 'export async function processRequest(payload: Payload) {', + ' const validationResult = validateRequest(payload)', + ' await insertRecord(validationResult)', + ' await dispatchRecord(validationResult)', + ' return retryDelivery(validationResult)', + '}', + '', + 'export const mergePair = (first: number, second: number) => first - second', + '', + 'export function echoDatum(datum: T) {', + ' return datum', + '}', + '', + 'export const styleText = (text: string) => text.toLowerCase().trim()', + ] + const helpers = [ + { + label: 'combinePair', + sourceLocation: 'L1', + expectedLine: 1, + symbolRange: { start: 1, end: 1 }, + }, + { + label: 'keepDatum', + sourceLocation: 'L3-L5', + expectedLine: 4, + symbolRange: { start: 3, end: 5 }, + }, + { + label: 'polishText', + sourceLocation: 'L7', + expectedLine: 7, + symbolRange: { start: 7, end: 7 }, + }, + { + label: 'mergePair', + sourceLocation: 'L16', + expectedLine: 16, + symbolRange: { start: 16, end: 16 }, + }, + { + label: 'echoDatum', + sourceLocation: 'L18-L20', + expectedLine: 19, + symbolRange: { start: 18, end: 20 }, + }, + { + label: 'styleText', + sourceLocation: 'L22', + expectedLine: 22, + symbolRange: { start: 22, end: 22 }, + }, + ] + try { + writeFileSync(sourceFile, sourceLines.join('\n'), 'utf8') + + for (const helper of helpers) { + const evidence = readQueryEvidenceSnippet(sourceFile, helper.symbolRange.start, { + question: QUESTION, + label: helper.label, + sourceLocation: helper.sourceLocation, + }) + + expect(evidence).toMatchObject({ scope: 'source_file' }) + const snippet = evidence?.snippet ?? '' + const renderedLines = evidence?.snippet.split('\n') ?? [] + expect(renderedLines.length).toBeLessThanOrEqual(4) + expect(snippet.length).toBeLessThanOrEqual(300) + + const renderedLineNumbers = renderedLines.map((line) => { + const match = /^L(\d+): (.*)$/.exec(line) + expect(match).not.toBeNull() + expect(match?.[2]?.length).toBeLessThanOrEqual(220) + return Number(match?.[1]) + }) + expect(renderedLineNumbers).toEqual([...renderedLineNumbers].sort((left, right) => left - right)) + expect(evidence?.lineNumber).toBe(renderedLineNumbers[0]) + + const expectedSource = sourceLines[helper.expectedLine - 1]! + .replace(/\s+/g, ' ').trim() + expect(renderedLines).toContain(`L${helper.expectedLine}: ${expectedSource}`) + expect( + renderedLineNumbers.filter((renderedLineNumber) => ( + renderedLineNumber >= helper.symbolRange.start + && renderedLineNumber <= helper.symbolRange.end + )), + ).toEqual([helper.expectedLine]) + + expect(renderedLines.some((line) => ( + line.includes('validateRequest') + || line.includes('insertRecord') + || line.includes('dispatchRecord') + || line.includes('retryDelivery') + ))).toBe(true) + } + } finally { + rmSync(root, { recursive: true, force: true }) + } + }) + + it('reserves a late neutral helper under long preceding file-match pressure', () => { + const { root, sourceFile } = createFixture() + const strongLine = "export const processRequest = async (payload: Payload) => retryDelivery(await dispatchRecord(await insertRecord(validateRequest(sanitize(payload)), { insertionMode: 'durable', validationMode: 'strict', dispatchMode: 'ordered', retryMode: 'exponential', handlingMode: 'recorded' })))" + const helperLine = "export const weaveTuple = (alpha: string, beta: string, gamma: string) => [alpha.trim(), beta.toUpperCase(), gamma.toLowerCase()].join(':')" + const sourceLines = [strongLine, '', helperLine] + try { + writeFileSync(sourceFile, sourceLines.join('\n'), 'utf8') + + const evidence = readQueryEvidenceSnippet(sourceFile, 3, { + question: QUESTION, + label: 'weaveTuple', + sourceLocation: 'L3', + }) + + expect(evidence).toEqual({ + snippet: `L3: ${helperLine}`, + lineNumber: 3, + scope: 'source_file', + }) + const renderedLines = evidence?.snippet.split('\n') ?? [] + const renderedLineNumbers = renderedLines.map((line) => Number(/^L(\d+):/.exec(line)?.[1])) + expect(renderedLineNumbers).toEqual([...renderedLineNumbers].sort((left, right) => left - right)) + expect(renderedLines.length).toBeLessThanOrEqual(4) + expect(evidence?.snippet.length).toBeLessThanOrEqual(300) + for (const line of renderedLines) { + const content = /^L\d+: (.*)$/.exec(line)?.[1] ?? '' + expect(content.length).toBeLessThanOrEqual(220) + } + } finally { + rmSync(root, { recursive: true, force: true }) + } + }) + it('leaves a helper-only split-file excerpt unchanged', () => { const { root, sourceFile } = createFixture() const helperLine = 'export const foldValue = (value: string) => sanitize(value)'