From ecd12e43ff8872cb000ad8443d3b8a17062f94eb Mon Sep 17 00:00:00 2001 From: garrytan Date: Mon, 2 Nov 2026 16:36:45 +0000 Subject: [PATCH] fix: #149 join stops at a labeled or located paragraph and after the fields (GST-987) 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 | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/review-ledger.ts b/lib/review-ledger.ts index 3a06a6bd2..dce6fde5d 100644 --- a/lib/review-ledger.ts +++ b/lib/review-ledger.ts @@ -164,7 +164,7 @@ export function parseFindings(reader: string, output: string, fixableRaises = tr } const detail = listItem && /^[-*+]\s/.test(t) && !locus && !label && !section && !!current && !current.list && !current.fields.size; if (detail && !blocks) { current!.raw += ` | ${t}`; continue; } - if (afterGap && current?.heading && !LIST_ITEM.test(t) && !HEADING.test(t) && !NUMBERED_HEAD.test(t)) { + if (afterGap && current?.heading && !current.fields.size && !LIST_ITEM.test(t) && !HEADING.test(t) && !NUMBERED_HEAD.test(t) && !LEAD_LABEL.test(t) && !LOCUS.test(t)) { current.raw += ` | ${t}`; if (blocks) current.label = 'CRITICAL'; else if (label) current.label = stronger(current.label, label); diff --git a/test/review-fixable-class.test.ts b/test/review-fixable-class.test.ts index b555d12c1..010781330 100644 --- a/test/review-fixable-class.test.ts +++ b/test/review-fixable-class.test.ts @@ -49,6 +49,12 @@ describe('native FIXABLE by review class (GST-987)', () => { expect(parseFindings('adversarial-native', output, false).map(f => f.label)).toEqual(['Medium', 'Low']); expect(parseFindings('adversarial-native', output, true).map(f => f.label)).toEqual(['CRITICAL', 'CRITICAL']); }); + test('a labeled or located paragraph after a numbered heading stays its own finding (#149 joins only plain body text)', () => { + for (const raises of [true, false]) { + expect(parseFindings('outside-voice', '### 1. P2 race in a.ts:3\n\nP0: also data loss in b.ts:9\n\nSeverity: Medium', raises).map(f => f.label)).toEqual(['P2', 'P0']); + expect(parseFindings('outside-voice', '### 1. P2 race in a.ts:3\n\nBody.\n\nP1: second issue in b.ts:9', raises).map(f => f.label)).toEqual(['P2', 'P1']); + } + }); test('collect reads the class from --manifest and defaults to the gate class without one', () => { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gst987-')); const out = path.join(dir, 'native.txt');