diff --git a/gitnexus/test/integration/local-backend-calltool.test.ts b/gitnexus/test/integration/local-backend-calltool.test.ts index 3fd1b0890..ee8bf6c5a 100644 --- a/gitnexus/test/integration/local-backend-calltool.test.ts +++ b/gitnexus/test/integration/local-backend-calltool.test.ts @@ -385,6 +385,31 @@ withTestLbugDB( expect(result.status).toBe('ambiguous'); const uids = (result.candidates ?? []).map((c: any) => c.uid); expect(uids).toContain('func:alpha'); + // Assert the non-symbol Tool node stays in the candidate set, not just + // that nothing crashed — a regression that silently dropped Tool from + // the lenient-binding match would otherwise pass the non-crash check. + expect(uids).toContain('Tool:alpha'); + }); + + it('ranks the kind-matching candidate first when kind is supplied (the --kind flag path)', async () => { + // 'alpha' is both a Function (func:alpha) and a Tool (Tool:alpha). + // kind only adds +0.20 in scoreCandidate, so 0.50 + 0.20 = 0.70 stays + // below the 0.95 confident-resolution threshold — the response is still + // ambiguous. What kind buys is ranking: the Function is promoted above + // the non-matching Tool. This exercises the scoreCandidate kind branch + // against a real DB rather than only through the mocked CLI unit test. + const result = await backend.callTool('impact', { + target: 'alpha', + kind: 'Function', + direction: 'upstream', + }); + expect(result).not.toHaveProperty('error'); + expect(result.status).toBe('ambiguous'); + const candidates = result.candidates ?? []; + expect(candidates[0]?.uid).toBe('func:alpha'); + expect(candidates[0]?.kind).toBe('Function'); + const tool = candidates.find((c: any) => c.uid === 'Tool:alpha'); + expect(candidates[0]?.score).toBeGreaterThan(tool?.score); }); }); }, diff --git a/gitnexus/test/unit/cli-impact-disambiguation.test.ts b/gitnexus/test/unit/cli-impact-disambiguation.test.ts index 7485153fa..507c3b8dd 100644 --- a/gitnexus/test/unit/cli-impact-disambiguation.test.ts +++ b/gitnexus/test/unit/cli-impact-disambiguation.test.ts @@ -25,6 +25,14 @@ vi.mock('../../src/mcp/local/local-backend.js', () => ({ }, })); +// impactCommand prints its result via fs.writeSync(fd 1, …). Silence that so +// the assertion-only test does not write JSON to the runner's stdout. tool.ts +// uses only writeSync from node:fs, so a full mock is safe here (matches the +// pattern in tool-direct-cli.test.ts). +vi.mock('node:fs', () => ({ + writeSync: vi.fn(), +})); + import { impactCommand } from '../../src/cli/tool.js'; describe('CLI impact disambiguation flags (#1907)', () => { diff --git a/gitnexus/test/unit/cli-index-help.test.ts b/gitnexus/test/unit/cli-index-help.test.ts index a50937ba7..3beaeff9a 100644 --- a/gitnexus/test/unit/cli-index-help.test.ts +++ b/gitnexus/test/unit/cli-index-help.test.ts @@ -196,13 +196,18 @@ describe('CLI help surface', () => { expect(result.stdout).toContain('--file '); }); - it('impact help keeps repo and include-tests flags', () => { + it('impact help keeps repo, include-tests, and disambiguation flags', () => { const result = runHelp('impact'); expect(result.status).toBe(0); expect(result.stdout).toContain('--depth '); expect(result.stdout).toContain('--include-tests'); expect(result.stdout).toContain('--repo '); + // Disambiguation flags (#1907) — mirror the context help test so a + // missing-flag regression on impact is caught here too. + expect(result.stdout).toContain('--uid '); + expect(result.stdout).toContain('--file '); + expect(result.stdout).toContain('--kind '); }); it('detect-changes help exposes compare scope and base-ref flags', () => {