R3.2.8.6-R1.3C-KK1-R6A-R1 Four-Language Heading Parity and Citation Whitespace Integrity Fix

#37
config.py CHANGED
@@ -195,7 +195,8 @@ def load_config():
195
  "abstract", "keyword", "keywords", "摘要", "关键词", "关键字",
196
  "reference", "references", "reference list", "参考文献",
197
  "acknowledgment", "acknowledgements", "致谢",
198
- "аннотация", "ключевые слова", "түйіндеме", "кілт сөздер"
 
199
  ]
200
  },
201
 
 
195
  "abstract", "keyword", "keywords", "摘要", "关键词", "关键字",
196
  "reference", "references", "reference list", "参考文献",
197
  "acknowledgment", "acknowledgements", "致谢",
198
+ "аннотация", "ключевые слова", "аңдатпа", "түйіндеме",
199
+ "түйін сөздер", "түйінді сөздер", "кілт сөздер"
200
  ]
201
  },
202
 
core/pipeline_agent.py CHANGED
@@ -2638,6 +2638,24 @@ SECTION: {section_name}
2638
  if re.search(r"\[?CITE-\d+\]?", sentence, re.IGNORECASE)
2639
  ]
2640
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2641
  @staticmethod
2642
  def _translation_numeric_regex():
2643
  # Canonical immutable numeric token used by both translation protection
@@ -2916,7 +2934,10 @@ Return exactly:
2916
  f"Citation semantic audit left multiple citations for {record['id']}: "
2917
  f"{sentence_violations[:2]}"
2918
  )
2919
- replacements[record["id"]] = revised
 
 
 
2920
 
2921
  if unsupported:
2922
  logging.warning(
@@ -3055,7 +3076,11 @@ Return exactly:
3055
  '',
3056
  f'No candidate met the conservative support threshold; best overlap={overlap}, coverage={coverage:.3f}.',
3057
  )
3058
- rebuilt.append(revised)
 
 
 
 
3059
  cursor = end
3060
  rebuilt.append(str(text)[cursor:])
3061
  recovered = ''.join(rebuilt)
 
2638
  if re.search(r"\[?CITE-\d+\]?", sentence, re.IGNORECASE)
2639
  ]
2640
 
2641
+ @staticmethod
2642
+ def _preserve_sentence_boundary_whitespace(original, revised):
2643
+ """Restore only the source sentence's outer whitespace envelope.
2644
+
2645
+ Citation audit models return sentence cores and callers historically
2646
+ stripped them before splice-back. When the original span begins with
2647
+ the inter-sentence space, losing that envelope joins adjacent sentences
2648
+ (for example ``evidence.ChatGPT``). Preserve boundary whitespace only;
2649
+ never normalize punctuation, DOI strings, decimals, or internal prose.
2650
+ """
2651
+ source = str(original or "")
2652
+ core = str(revised or "").strip()
2653
+ if not core:
2654
+ return ""
2655
+ leading = source[: len(source) - len(source.lstrip())]
2656
+ trailing = source[len(source.rstrip()) :]
2657
+ return f"{leading}{core}{trailing}"
2658
+
2659
  @staticmethod
2660
  def _translation_numeric_regex():
2661
  # Canonical immutable numeric token used by both translation protection
 
2934
  f"Citation semantic audit left multiple citations for {record['id']}: "
2935
  f"{sentence_violations[:2]}"
2936
  )
2937
+ replacements[record["id"]] = self._preserve_sentence_boundary_whitespace(
2938
+ record["original"],
2939
+ revised,
2940
+ )
2941
 
2942
  if unsupported:
2943
  logging.warning(
 
3076
  '',
3077
  f'No candidate met the conservative support threshold; best overlap={overlap}, coverage={coverage:.3f}.',
3078
  )
3079
+ rebuilt.append(
3080
+ self._preserve_sentence_boundary_whitespace(original, revised)
3081
+ if revised
3082
+ else ""
3083
+ )
3084
  cursor = end
3085
  rebuilt.append(str(text)[cursor:])
3086
  recovered = ''.join(rebuilt)
smartpaper_restore_bridge/frontend/index.html CHANGED
@@ -401,9 +401,11 @@
401
  }
402
 
403
  const UNNUMBERED_HEADINGS = new Set([
404
- "abstract","keywords","references","摘要","关键词","参考文献",
405
- "аннотация","ключевые слова","литература","список литературы",
406
- "аңдатпа","аннотация","түйінді сөздер","кілт сөздер","әдебиеттер","пайдаланылған әдебиеттер"
 
 
407
  ]);
408
 
409
  function cleanHeadingTitle(value) {
 
401
  }
402
 
403
  const UNNUMBERED_HEADINGS = new Set([
404
+ "abstract","keyword","keywords","references","reference list",
405
+ "摘要","关键词","关键字","参考文献",
406
+ "аннотация","ключевое слово","ключевые слова","литература","список литературы",
407
+ "аңдатпа","түйіндеме","түйін сөздер","түйінді сөздер","кілт сөздер",
408
+ "әдебиеттер","пайдаланылған әдебиеттер"
409
  ]);
410
 
411
  function cleanHeadingTitle(value) {