From 8b591faf9ca9ef1282fa8d1a1a9577381a8bdc2c Mon Sep 17 00:00:00 2001 From: garrytan Date: Mon, 2 Nov 2026 16:34:05 +0000 Subject: [PATCH] fix: verify re-derives native labels with the collect's class (GST-987, after #3717) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- lib/review-ledger.ts | 2 +- test/review-fixable-class.test.ts | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/review-ledger.ts b/lib/review-ledger.ts index bcd5bb785..3a06a6bd2 100644 --- a/lib/review-ledger.ts +++ b/lib/review-ledger.ts @@ -433,7 +433,7 @@ export function verify(ledger: string): { rows: VerifyRow[]; clean: boolean; bri notes.push(typeof o.file === 'string' ? 'output_file_missing' : 'output_file_unrecorded'); differs.push(...ids); } else if (promptHash(text) === o.sha256) { - const parsed = parseFindings(reader, text); + const parsed = parseFindings(reader, text, o.fixable_raises !== false); const off = ids.filter((id, k) => { const m = lines.find(l => l.id === id); return !m || parsed[k]?.label !== m.label || parsed[k]?.raw !== m.raw; }); if (unavailableOutput(o) && parsed.length) { status = 'MISMATCH'; notes.push('unavailable_output_has_findings'); } else if (!unavailableOutput(o)) { diff --git a/test/review-fixable-class.test.ts b/test/review-fixable-class.test.ts index 7e233ffbe..b555d12c1 100644 --- a/test/review-fixable-class.test.ts +++ b/test/review-fixable-class.test.ts @@ -3,7 +3,7 @@ import { spawnSync } from 'node:child_process'; import * as fs from 'node:fs'; import * as os from 'node:os'; import * as path from 'node:path'; -import { fixableRaises, parseFindings } from '../lib/review-ledger'; +import { collect, fixableRaises, parseFindings, verify } from '../lib/review-ledger'; const ROOT = path.resolve(import.meta.dir, '..'); const NATIVE = fs.readFileSync(path.join(ROOT, 'test/fixtures/review-ledger/gsta-141-native.md'), 'utf8').split('\n').filter(l => /^\d+\. /.test(l)).join('\n\n'); @@ -73,4 +73,13 @@ describe('native FIXABLE by review class (GST-987)', () => { expect(labels(['--manifest', foreign])).toEqual(['CRITICAL', 'CRITICAL']); fs.rmSync(dir, { recursive: true, force: true }); }); + test('verify re-derives a code-class collect with the class it was collected under', () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gst987v-')); + const out = path.join(dir, 'native.txt'); + fs.writeFileSync(out, NATIVE + '\n'); + const c = collect(path.join(dir, 'l.jsonl'), 'adversarial-native', NATIVE + '\n', path.join(dir, 'm.jsonl'), out, undefined, undefined, false); + expect(c.lines.map(l => l.label)).toEqual(['Medium', 'Low']); + expect(JSON.stringify(verify(path.join(dir, 'l.jsonl')))).not.toContain('merged_line_differs'); + fs.rmSync(dir, { recursive: true, force: true }); + }); });