diff --git a/.github/scripts/check_pr_body.py b/.github/scripts/check_pr_body.py
index 70881e69bcf..4711997323f 100644
--- a/.github/scripts/check_pr_body.py
+++ b/.github/scripts/check_pr_body.py
@@ -25,6 +25,7 @@ HTML_COMMENT_PATTERN: Final = re.compile(r"", re.DOTALL)
HEADING_PATTERN: Final = re.compile(r"^#{2,6}\s+(?P
.+?)\s*$")
BULLET_PATTERN: Final = re.compile(r"^\s*(?:[-*+]|\d+[.)])\s+(?P.*)$")
LABEL_PATTERN: Final = re.compile(r"^[^-*+].*:\s*$")
+FENCE_PATTERN: Final = re.compile(r"^\s*(?:```|~~~)")
@dataclass(frozen=True, slots=True)
@@ -48,9 +49,21 @@ def strip_html_comments(body: str) -> str:
def split_sections(body: str) -> tuple[Section, ...]:
lines: Final = tuple(body.split("\n"))
- headings: Final = tuple(
- (index, match.group("title")) for index, line in enumerate(lines) if (match := HEADING_PATTERN.match(line))
- )
+
+ def scan(
+ acc: tuple[bool, tuple[tuple[int, str], ...]],
+ item: tuple[int, str],
+ ) -> tuple[bool, tuple[tuple[int, str], ...]]:
+ in_fence, headings = acc
+ index, line = item
+ if FENCE_PATTERN.match(line):
+ return (not in_fence, headings)
+ if in_fence:
+ return acc
+ match: Final = HEADING_PATTERN.match(line)
+ return (in_fence, (*headings, (index, match.group("title")))) if match else acc
+
+ _, headings = reduce(scan, tuple(enumerate(lines)), (False, ()))
ends: Final = tuple(index for index, _ in headings[1:]) + (len(lines),)
return tuple(Section(title=title, lines=lines[start + 1 : end]) for (start, title), end in zip(headings, ends))
@@ -92,8 +105,9 @@ def check_bullet_section(section: Section) -> tuple[Violation, ...]:
def is_placeholder_line(line: str) -> bool:
bullet_match: Final = BULLET_PATTERN.match(line)
- content: Final = bullet_match.group("text").strip() if bullet_match else line.strip()
- return content == "..." or any(token in line for token in PLACEHOLDER_TOKENS)
+ if bullet_match and bullet_match.group("text").strip() == "...":
+ return True
+ return any(token in line for token in PLACEHOLDER_TOKENS)
def check_placeholders(sections: tuple[Section, ...]) -> tuple[Violation, ...]:
diff --git a/tests/test_litellm/test_github_check_pr_body.py b/tests/test_litellm/test_github_check_pr_body.py
index edf3587e42f..5010829d9d2 100644
--- a/tests/test_litellm/test_github_check_pr_body.py
+++ b/tests/test_litellm/test_github_check_pr_body.py
@@ -109,3 +109,28 @@ def test_multiline_html_comment_spanning_section_is_stripped(checker):
violations = checker.check_body(body, ("litellm/main.py",))
assert len(violations) == 1
assert violations[0].section == "QA runbook"
+
+
+def test_bare_ellipsis_in_proof_output_is_not_a_placeholder(checker):
+ body = (
+ "## Screenshots / Proof of Fix\n\n"
+ "```\n"
+ "$ curl http://localhost:4000/v1/chat/completions ...\n"
+ "{\"id\": \"chatcmpl-abc\",\n"
+ " ...\n"
+ " \"usage\": {\"prompt_tokens\": 5}}\n"
+ "```\n"
+ )
+ assert checker.check_body(body, ()) == ()
+
+
+def test_headings_inside_fenced_block_do_not_open_new_sections(checker):
+ body = (
+ "## Screenshots / Proof of Fix\n\n"
+ "Quoted template excerpt:\n\n"
+ "```markdown\n"
+ "## Caveats (if any)\n\n"
+ "Some prose paragraph that is not a bullet at all\n"
+ "```\n"
+ )
+ assert checker.check_body(body, ()) == ()