The release job now checks out the repo and extracts the CHANGELOG.md
section matching the pushed tag (leading v stripped) with
scripts/extract-changelog-section.sh, and passes it as body_path. If the
section is missing it logs a warning and falls back to a generic body
naming the tag and pointing at CHANGELOG.md.
scripts/test-extract-changelog-section.sh covers the found and missing
cases against a fake CHANGELOG in a temp dir; the CI shell job runs it
and shellchecks both scripts.