@@ -224,20 +224,24 @@ mkdir -p .roo/tmp/release-notes
224224gh release view vX.Y.Z --repo RooCodeInc/Roo-Code --json body --jq '.body' > .roo/tmp/release-notes/changelog_vX.Y.Z.md
225225 ]]> </save_body_to_file >
226226 <fetch_changelog ><![CDATA[
227- # Fetch CHANGELOG.md at tag vX.Y.Z; fallback to main, then extract vX.Y.Z section
227+ # Fetch CHANGELOG.md from main branch FIRST for hero image discovery.
228+ # Hero images are often added retroactively after release, so the current main
229+ # branch has the most up-to-date images. Only fall back to the release tag if main fails.
228230TMP_DIR=".roo/tmp/release-notes"
229231CHANGELOG_TAG_FILE="$TMP_DIR/CHANGELOG_vX.Y.Z.md"
230232SECTION_FILE="$TMP_DIR/CHANGELOG_section_vX.Y.Z.md"
231- # Try tag first
232- if gh api "repos/RooCodeInc/Roo-Code/contents/CHANGELOG.md?ref=vX.Y.Z " --jq '.content' >/tmp/chlog64.txt 2>/dev/null; then
233+ # Try main first (has retroactively-added hero images)
234+ if gh api "repos/RooCodeInc/Roo-Code/contents/CHANGELOG.md" --jq '.content' >/tmp/chlog64.txt 2>/dev/null; then
233235 base64 -D </tmp/chlog64.txt > "$CHANGELOG_TAG_FILE" || true
234- # Fallback to main
235- elif gh api "repos/RooCodeInc/Roo-Code/contents/CHANGELOG.md" --jq '.content' >/tmp/chlog64.txt 2>/dev/null; then
236+ # Fallback to tag if main fails
237+ elif gh api "repos/RooCodeInc/Roo-Code/contents/CHANGELOG.md?ref=vX.Y.Z " --jq '.content' >/tmp/chlog64.txt 2>/dev/null; then
236238 base64 -D </tmp/chlog64.txt > "$CHANGELOG_TAG_FILE" || true
237239else
238240 : > "$CHANGELOG_TAG_FILE"
239241fi
240242# Extract the vX.Y.Z section if present
243+ # CRITICAL: If the version header is not found, create an EMPTY section file.
244+ # Do NOT fall back to the entire changelog—that would pull images from other versions.
241245if [ -s "$CHANGELOG_TAG_FILE" ]; then
242246 START_LINE=$(grep -nE '^[#]{2,3}[[:space:]]*\[?v?X\.Y\.Z\]?' "$CHANGELOG_TAG_FILE" | head -n1 | cut -d: -f1 || true)
243247 if [ -n "${START_LINE:-}" ]; then
@@ -249,32 +253,28 @@ if [ -s "$CHANGELOG_TAG_FILE" ]; then
249253 tail -n +"$START_LINE" "$CHANGELOG_TAG_FILE" > "$SECTION_FILE"
250254 fi
251255 else
252- cp "$CHANGELOG_TAG_FILE" "$SECTION_FILE"
256+ # Version header not found—create empty section to avoid pulling images from other versions
257+ : > "$SECTION_FILE"
253258 fi
254259else
255260 : > "$SECTION_FILE"
256261fi
257262 ]]> </fetch_changelog >
258263 <extract_candidates ><![CDATA[
259- # Build candidate list from both the release body and extracted changelog section (absolute and relative paths)
264+ # Build candidate list ONLY from the extracted changelog section for the target version.
265+ # Do NOT extract from the full release body—it often contains the entire changelog,
266+ # which would pull images from unrelated versions.
260267CANDIDATES_FILE=".roo/tmp/release-notes/image_candidates_vX.Y.Z.txt"
268+ SECTION_FILE=".roo/tmp/release-notes/CHANGELOG_section_vX.Y.Z.md"
261269: > "$CANDIDATES_FILE"
262270
263- # From release body markdown images (absolute or relative)
264- grep -Eo '!\[[^]]*\]\(([^)]+)\)' .roo/tmp/release-notes/changelog_vX.Y.Z.md 2>/dev/null \
265- | sed -E 's/.*\(([^)]+)\).*/\1/' | grep -Ei '\.(png|jpe?g|gif|webp)' >> "$CANDIDATES_FILE" || true
266-
267- # From release body bare URLs (absolute or relative)
268- grep -Eo 'https?://[^ )]+' .roo/tmp/release-notes/changelog_vX.Y.Z.md 2>/dev/null | grep -Ei '\.(png|jpe?g|gif|webp)' >> "$CANDIDATES_FILE" || true
269- grep -Eo '(/[^ )]+|[A-Za-z0-9_./-]+)\.(png|jpe?g|gif|webp)' .roo/tmp/release-notes/changelog_vX.Y.Z.md 2>/dev/null >> "$CANDIDATES_FILE" || true
270-
271271# From CHANGELOG section markdown images (absolute or relative)
272- grep -Eo '!\[[^]]*\]\(([^)]+)\)' .roo/tmp/release-notes/CHANGELOG_section_vX.Y.Z.md 2>/dev/null \
272+ grep -Eo '!\[[^]]*\]\(([^)]+)\)' "$SECTION_FILE" 2>/dev/null \
273273 | sed -E 's/.*\(([^)]+)\).*/\1/' | grep -Ei '\.(png|jpe?g|gif|webp)' >> "$CANDIDATES_FILE" || true
274274
275275# From CHANGELOG section bare URLs (absolute or relative)
276- grep -Eo 'https?://[^ )]+' .roo/tmp/release-notes/CHANGELOG_section_vX.Y.Z.md 2>/dev/null | grep -Ei '\.(png|jpe?g|gif|webp)' >> "$CANDIDATES_FILE" || true
277- grep -Eo '(/[^ )]+|[A-Za-z0-9_./-]+)\.(png|jpe?g|gif|webp)' .roo/tmp/release-notes/CHANGELOG_section_vX.Y.Z.md 2>/dev/null >> "$CANDIDATES_FILE" || true
276+ grep -Eo 'https?://[^ )]+' "$SECTION_FILE" 2>/dev/null | grep -Ei '\.(png|jpe?g|gif|webp)' >> "$CANDIDATES_FILE" || true
277+ grep -Eo '(/[^ )]+|[A-Za-z0-9_./-]+)\.(png|jpe?g|gif|webp)' "$SECTION_FILE" 2>/dev/null >> "$CANDIDATES_FILE" || true
278278
279279# Deduplicate
280280if [ -s "$CANDIDATES_FILE" ]; then
289289 </step >
290290
291291 <step number =" 1b" >
292- <action >Download hero image via curl to static/img/v[VERSION]/v[VERSION].png and persist frontmatter image path </action >
292+ <action >Resolve hero image from discovered candidates, falling back to social-share when none exist </action >
293293 <command ><![CDATA[
294294VERSION="X.Y.Z"
295+ CANDIDATES_FILE=".roo/tmp/release-notes/image_candidates_v$VERSION.txt"
296+ FRONTMATTER_FILE=".roo/tmp/release-notes/frontmatter_image_v$VERSION.txt"
297+
298+ # If no candidates were discovered, skip download entirely and use social-share
299+ if [ ! -s "$CANDIDATES_FILE" ]; then
300+ mkdir -p "$(dirname "$FRONTMATTER_FILE")"
301+ echo "/img/social-share.jpg" > "$FRONTMATTER_FILE"
302+ exit 0
303+ fi
304+
305+ # Try the first candidate URL/path as the hero image source
295306mkdir -p "static/img/v$VERSION"
296307OUT="static/img/v$VERSION/v$VERSION.png"
297- RAW_URL="https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/releases/$VERSION-release.png"
298- curl -L "$RAW_URL" -o "$OUT" || true
308+ SRC="$(head -n1 "$CANDIDATES_FILE")"
309+
310+ # If SRC is a relative docs path, prefix it with the raw GitHub base for Roo-Code
311+ if echo "$SRC" | grep -qE '^(https?://)'; then
312+ URL="$SRC"
313+ else
314+ # Treat as repository-relative path; adjust as needed if release assets move
315+ URL="https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/$SRC"
316+ fi
317+
318+ curl -L "$URL" -o "$OUT" || true
299319if [ -s "$OUT" ]; then
300- echo "/img/v$VERSION/v$VERSION.png" > ".roo/tmp/release-notes/frontmatter_image_v$VERSION.txt "
320+ echo "/img/v$VERSION/v$VERSION.png" > "$FRONTMATTER_FILE "
301321else
302- echo "/img/social-share.jpg" > ".roo/tmp/release-notes/frontmatter_image_v$VERSION.txt "
322+ echo "/img/social-share.jpg" > "$FRONTMATTER_FILE "
303323fi
304324 ]]> </command >
305325 <notes >
306- - If curl fails or the URL is invalid, the persisted path will be /img/social-share.jpg
307- - Prefer PNG when multiple candidates are present
326+ - Skip hero image download entirely when no candidates were discovered; default to /img/social-share.jpg
327+ - When candidates exist, attempt to download the first one and persist it as /img/v$VERSION/v$VERSION.png
328+ - If download fails or the file is empty, fall back to /img/social-share.jpg
329+ - Prefer PNG when multiple candidates are present (candidates list should already be filtered/ordered)
308330 </notes >
309331 </step >
310332
@@ -670,6 +692,10 @@ gh pr list --repo RooCodeInc/Roo-Code --state merged --base main --limit 1000 \
670692 </rule >
671693 <rule priority =" CRITICAL" >
672694 For each PR, the parent MUST create a subtask via new_task. The parent MUST NOT write PR analysis entries; only subtasks may append to .roo/tmp/release-notes/temp_pr_analysis_v[version].md. Do not proceed to changelog_alignment or compilation until all PR subtasks complete.
695+ Even when the parent already has the PR number, title, description, or a user‑provided
696+ summary list, it MUST still create and wait on the per‑PR subtask. These summaries are
697+ insufficient for functional understanding of the change, discovery of linked issues, and
698+ correct contributor attribution (PR authors and issue reporters).
673699 </rule >
674700 <rule priority =" CRITICAL" >
675701 Use the simplified PR extraction command for consistent results
0 commit comments