"""Shared Markdown-section parsing for the PR-template tooling. `validate.py` (the merge gate) and the release-time changelog harvester (`.github/scripts/changelog/generate.py`) both need to pull a named `##` section out of a PR body. Keeping that logic in one place means the gate and the harvester can never drift on what counts as the "## Changelog" section. """ from __future__ import annotations import re _HEADING_RE = re.compile(r"(?im)^\s*##\s+(.+?)\s*$") _HTML_COMMENT_RE = re.compile(r"", re.DOTALL) _CHECKBOX_RE = re.compile(r"(?im)^\s*-\s*\[(?P[ xX])\]\s*(?P