Просмотр исходного кода

fix: exclude dialogue lines from paragraph fragmentation detection

Dialogue paragraphs (starting with quotes/brackets) are naturally short
and should not count toward the "consecutive short paragraphs" warning.
This was the #1 cause of audit failures in all Chinese books (14-25%
pass rate), inflating issue counts with false positives.

Discovered via autoresearch: 3/5 books had paragraph fragmentation as
their top audit issue category, all driven by dialogue-heavy scenes.
Ma 7 месяцев назад
Родитель
Сommit
59b1f191a3
1 измененных файлов с 10 добавлено и 3 удалено
  1. 10 3
      packages/core/src/agents/post-write-validator.ts

+ 10 - 3
packages/core/src/agents/post-write-validator.ts

@@ -503,17 +503,24 @@ export function detectParagraphShapeWarnings(
   return violations;
 }
 
+function isDialogueParagraph(paragraph: string): boolean {
+  const trimmed = paragraph.trim();
+  return /^[""「『'《]/.test(trimmed) || /^[""]/.test(trimmed) || /^——/.test(trimmed);
+}
+
 function analyzeParagraphShape(content: string, language: "zh" | "en"): ParagraphShape {
   const paragraphs = extractParagraphs(content);
+  // Exclude dialogue lines from short paragraph counting — dialogue is naturally short
+  const narrativeParagraphs = paragraphs.filter((p) => !isDialogueParagraph(p));
   const shortThreshold = language === "en" ? 120 : 35;
-  const shortParagraphs = paragraphs.filter((paragraph) => paragraph.length < shortThreshold);
+  const shortParagraphs = narrativeParagraphs.filter((paragraph) => paragraph.length < shortThreshold);
   const averageLength = paragraphs.length > 0
     ? paragraphs.reduce((sum, paragraph) => sum + paragraph.length, 0) / paragraphs.length
     : 0;
 
   let maxConsecutiveShort = 0;
   let currentConsecutive = 0;
-  for (const paragraph of paragraphs) {
+  for (const paragraph of narrativeParagraphs) {
     if (paragraph.length < shortThreshold) {
       currentConsecutive++;
       maxConsecutiveShort = Math.max(maxConsecutiveShort, currentConsecutive);
@@ -526,7 +533,7 @@ function analyzeParagraphShape(content: string, language: "zh" | "en"): Paragrap
     paragraphs,
     shortThreshold,
     shortParagraphs,
-    shortRatio: paragraphs.length > 0 ? shortParagraphs.length / paragraphs.length : 0,
+    shortRatio: narrativeParagraphs.length > 0 ? shortParagraphs.length / narrativeParagraphs.length : 0,
     averageLength,
     maxConsecutiveShort,
   };