diff --git a/.github/workflows/gitnexus-review-agent.yml b/.github/workflows/gitnexus-review-agent.yml index 039e772fb..080b45ada 100644 --- a/.github/workflows/gitnexus-review-agent.yml +++ b/.github/workflows/gitnexus-review-agent.yml @@ -1748,11 +1748,16 @@ jobs: throw new Error('context tool result is not strict JSON'); } validateBoundedJson(decoded, { nodes: 0 }); + // A line range is what the trusted prescan calls an indexable + // symbol, so a bare File node — `context({name: 'AGENTS.md'})` — + // must not pass for a review of that file's contents. if ( !isRecord(decoded) || Object.hasOwn(decoded, 'error') || decoded.status !== 'found' || - !isRecord(decoded.symbol) + !isRecord(decoded.symbol) || + !Number.isFinite(decoded.symbol.startLine) || + !Number.isFinite(decoded.symbol.endLine) ) { rejected.unresolved += 1; return false; diff --git a/gitnexus/test/unit/review-agent-workflow.test.ts b/gitnexus/test/unit/review-agent-workflow.test.ts index 59cbb1c89..6ed37b5ad 100644 --- a/gitnexus/test/unit/review-agent-workflow.test.ts +++ b/gitnexus/test/unit/review-agent-workflow.test.ts @@ -1776,6 +1776,27 @@ describe('gitnexus review-agent workflow security contract', () => { expect(structural.artifact.failure_code).toBe('invalid_execution_transcript'); }); + it('refuses a bare File node as evidence, matching the prescan definition of indexable', () => { + const fileNode = runArtifactScenario({ + rawTranscript: JSON.stringify( + reviewTranscript({ + toolInput: { name: 'status.ts' }, + toolResultContent: JSON.stringify({ + status: 'found', + symbol: { + uid: `File:${CHANGED_PATH}`, + name: 'status.ts', + kind: 'File', + filePath: CHANGED_PATH, + }, + }), + }), + ), + }); + expect(fileNode.artifact.failure_code).toBe('missing_graph_evidence'); + expect(fileNode.stderr).toContain('results that resolved nothing: 1'); + }); + it('scopes a deletion-only PR to the merge-base set instead of an empty head set', () => { const deletedPath = 'gitnexus/src/cli/deleted-command.ts'; const headScopedCall = runArtifactScenario({