From f3810d4705bdcd36142e56346d5fd680ffdf8a44 Mon Sep 17 00:00:00 2001 From: garrytan Date: Mon, 2 Nov 2026 12:51:23 +0000 Subject: [PATCH] fix(review-ledger): a lead's file:line has no runaway backtracking and may be a range; a mid-line Severity field must close its clause (GST-976 review) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- lib/review-ledger.ts | 8 ++++---- test/review-dispatch.test.ts | 8 ++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/review-ledger.ts b/lib/review-ledger.ts index 0985ffe22..a4001aba3 100644 --- a/lib/review-ledger.ts +++ b/lib/review-ledger.ts @@ -69,17 +69,17 @@ export interface Stated { severity?: string; blocks?: string } const STATED_SEVERITY = new RegExp(`(?]\\s+|\\d+[.)]\\s+)?\\**\\s*Severity\\**\\s*:?|(?:[.;,|()]\\s*|\\s[—–-]\\s*)\\**\\s*Severity\\**\\s*:)\\s*\\**\\s*(${LABELS})(?![A-Za-z0-9])`, 'gi'); +const SEVERITY_FIELD = new RegExp(`(?:^(?:[-*+>]\\s+|\\d+[.)]\\s+)?\\**\\s*Severity\\**\\s*:?|(?:[.;,|()]\\s*|\\s[—–-]\\s*)\\**\\s*Severity\\**\\s*:)\\s*\\**\\s*(${LABELS})(?![A-Za-z0-9])(?=\\**\\s*(?:$|[.;,|()*—–]|-\\s|Blocks))`, 'gi'); /** * A label leading its line past list, quote, heading, emphasis and emoji marks (one mark per step, so a long divider stays linear) * and an optional file:line, closed by a mark or a separator, or by a space, comma or parenthesis after an all-caps word ("[P0] …", * "1. **High**: …", "### CRITICAL: …", "1. api.ts:10 CRITICAL: …", "1. CRITICAL missing auth"): the reader's own label, which a * Severity field never lowers. "P0 pilot …" is not one. */ -const LEAD_LABEL = new RegExp(`^(?:[^\\p{L}\\p{N}\\s]\\s*|\\d+[.)]\\s*)*(?:[\\w./-]+:\\d+[^\\p{L}\\p{N}\\s]*\\s+(?:[^\\p{L}\\p{N}\\s]\\s*)*)?(${LABELS})(?=[*_\`\\])]|\\s*[:|—–]|\\s+-\\s|\\s*$|(?<=[A-Z]{3})[\\s,(.])`, 'u'); +const LEAD_LABEL = new RegExp(`^(?:[^\\p{L}\\p{N}\\s]\\s*|\\d+[.)]\\s*)*(?:\\w[\\w./-]*:\\d+(?:[-–:,]\\s*\\d+)*[^\\p{L}\\p{N}\\s]*\\s+(?:[^\\p{L}\\p{N}\\s]\\s*)*)?(${LABELS})(?=[*_\`\\])]|\\s*[:|—–]|\\s+-\\s|\\s*$|(?<=[A-Z]{3})[\\s,(.])`, 'u'); const STATED_BLOCKS = /(? = [['1. CRITICAL missing auth. Severity: Low', 'CRITICAL'], ['1. CRITICAL, missing auth on DELETE. Severity: Low', 'CRITICAL'], ['1. CRITICAL (api.ts:10) missing auth. Severity: Low', 'CRITICAL'], ['1. The P0 pilot table drops a row (t.md:3) Severity: Low', 'Low'], - ['1. The P0 pilot table drops a row\nSeverity Low', 'Low'], ['1. The P0 pilot table drops a row\n**Severity** Low', 'Low']]; + ['1. The P0 pilot table drops a row\nSeverity Low', 'Low'], ['1. The P0 pilot table drops a row\n**Severity** Low', 'Low'], + ['1. Bypass x.ts:3 is CRITICAL (Severity: Low in pass 1)', 'CRITICAL'], ['Still open: x.ts:3 is CRITICAL, Severity: Low in pass 1 understated it', 'CRITICAL'], + ['1. lib/x.ts:42-58 CRITICAL: drops rows. Severity: Low', 'CRITICAL'], ['1. lib/x.ts:42:7 CRITICAL: drops rows. Severity: Low', 'CRITICAL'], + ['1. (lib/x.ts:42, 50) CRITICAL: drops rows. Severity: Low', 'CRITICAL']]; for (const [output, label] of p2) expect([output, parseFindings('outside-voice', output).map(f => f.label)]).toEqual([output, [label]]); const t0 = performance.now(); for (const run of ['='.repeat(60), '-'.repeat(60), '|' + '-'.repeat(60) + '|', '🔴'.repeat(60), '. '.repeat(60), '-.'.repeat(60), '`'.repeat(60)]) for (const tail of [' P0 pilot table', ' High-risk', ' CRITICAL findings follow', ' a.ts:3 P0 pilot']) parseFindings('outside-voice', run + tail + '. Severity: Low'); - expect(performance.now() - t0).toBeLessThan(500); + parseFindings('outside-voice', '-'.repeat(16000) + ' P0 pilot table. Severity: Low'); + expect(performance.now() - t0).toBeLessThan(1000); }); // Value: protects=a non-review the same dispatch later answers with a review is voided (counted, VERIFY clean), and a failed outside