.agents/skills/release-notes/SKILL.md
Generate polished website release notes for SkiaSharp versions.
This skill is used both by the update-release-notes agentic workflow (automatically
on push to main, release/* branches, and tags) and manually when regenerating,
correcting, or bulk-processing release notes.
Ask the user which version(s) to generate, or infer from context:
3.119.2release/4.147.0-preview.1 or main3.119.0, 3.119.1, 3.119.2Run the script to collect raw PR data and write it to the version file:
python3 .agents/skills/release-notes/scripts/generate-release-notes.py --branch release/4.147.0-preview.1
python3 .agents/skills/release-notes/scripts/generate-release-notes.py --branch main
This writes raw PR data to documentation/docfx/releases/{version}.md or
documentation/docfx/releases/{version}-unreleased.md depending on the branch type,
and regenerates TOC/index. All data comes from git history — no API calls or tokens needed.
When TOC/index are regenerated, the script also prunes stale unreleased pages: any
{version}-unreleased.md whose stable {version}.md already exists is deleted, because
that version has shipped and the line has moved on to the next patch (e.g. once
3.119.4.md exists, 3.119.4-unreleased.md is removed in favour of 3.119.5-unreleased.md).
An unreleased page is still listed in its minor group even when no stable page of that exact
version exists yet (e.g. 3.119.5-unreleased.md before 3.119.5 ships).
The file starts with an HTML comment block containing both metadata (version, status, branch, diff range, PR count) AND the raw PR list. Below the comment is a skeleton heading with a placeholder for polished content. The raw data comment must be preserved in the final file.
IMPORTANT: The script prints a summary at the end listing ALL files to polish:
========================================
Files to polish:
- documentation/docfx/releases/4.147.0.md
- documentation/docfx/releases/3.119.5-unreleased.md
- documentation/docfx/releases/4.148.0-unreleased.md
========================================
You MUST polish every file in the "Files to polish" list — not just the first one. Read each file to get its raw data and metadata, then rewrite it with polished content.
Read documentation/docfx/releases/TEMPLATE.md. This is a real example of a polished
release notes page. Match its structure, tone, and formatting exactly.
Determine the version's status from the HTML comment block in the file (status: unreleased, status: preview, or status: stable):
Released {date} + NuGet link + GitHub Release linkPreview only + preview NuGet link + GitHub Release link> **Upcoming release** · In development · Not yet available on NuGetsuperseded: line is present in the comment block): the version was a
preview that will never ship as stable. Keep the script-generated
> **Preview only** · Superseded by [X.Y.Z](...) · Never released as stable … header and
add a short note in Highlights that the work rolled up into the superseding version.supersedes: line is present in the comment block): this version rolls
up one or more skipped preview-only versions. Keep the script-generated
> **Supersedes [X.Y.Z](...)** · Rolls up preview-only work … note and mention in
Highlights that the skipped preview work is rolled up cumulatively. This is the back-link
that makes the supersede relationship two-way (the superseded page points forward, the
successor points back).Occasionally a minor ships previews but is skipped before going stable — e.g. 4.147
was previewed but abandoned in favour of 4.148. This is handled automatically — no
configuration is normally required:
Automatic cumulative base. When choosing the diff base for a new minor (and for
main), the script picks the most recent prior version that actually shipped a stable
git tag, skipping any minor that only had previews. So 4.148's notes roll up all
the skipped 4.147 work instead of showing a tiny delta. The same skip applies to
point releases: a stable patch bases on the most recent previous patch that shipped
stable, so e.g. 3.119.4 rolls up the preview-only 3.119.3 (the 3.119.3 page still
keeps its own notes — duplication across the two pages is expected and fine).
Automatic supersede label (two-way). A version that has only preview tags is flagged as
superseded once a newer version is known. A newer version is "known" from a later
release/* branch or v* tag, or from main itself: if main's in-development
SKIASHARP_VERSION is newer and the preview-only version's minor line was never branched
for servicing (no release/X.Y.x), main's version supersedes it. So with main on
4.148.0 and only release/4.147.0-preview.* branches (no release/4.147.x), 4.147.0
is flagged superseded by 4.148.0 immediately — no 4.148 branch or tag required. The
page is forced to preview status and rendered with a "Preview only · Superseded by
4.148.0 · Never released as stable" header. The label links to the successor's published
page ({ver}.md) when it exists, otherwise to its in-development page
({ver}-unreleased.md). Until a newer version is known, the version is just a normal preview.
The relationship is rendered both ways: the successor page (computed by the inverse
detect_supersedes) carries a supersedes: data-block line and a
"Supersedes [X.Y.Z] · Rolls up preview-only work …" note, so e.g. 4.148.0 points back
to 4.147.0, 3.119.4 to 3.119.3, and 3.119.0 to 3.118.0 — automatically, without
the AI having to infer it from the diff base.
Detection is purely tag/branch/
main-version based, so no configuration file is needed. (If a manual override is ever required it can be reintroduced later; for now the automatic behaviour is the only path.)
When polishing a superseded page, keep the script-generated "Preview only · Superseded by …" header and add a one-line note in Highlights that the work rolled up into the successor. When polishing a successor page, keep the script-generated "Supersedes …" note and add a one-line note in Highlights that the skipped preview work is rolled up cumulatively.
For every file listed in the script's "Files to polish" output, write polished release notes below the raw data HTML comment block.
CRITICAL: Preserve the raw data comment. The <!-- RAW PR DATA ... --> comment block at
the top of the file must remain intact. Replace everything AFTER it (the skeleton heading and
placeholder) with polished content. When you write the polished content, start with the
<!-- Generated: ... --> timestamp line, then the # Version X.Y.Z heading, then the rest.
The final file structure should be:
<!-- RAW PR DATA — Do not remove this comment block. ... -->
<!-- Generated: YYYY-MM-DDTHH:MM:SSZ by {model-name} -->
# Version X.Y.Z
> **theme** · status · links
## Highlights
...
Each file has its own HTML comment block with version, status, branch, and diff range.
CRITICAL: Each file is independent. Only use the raw PR data that is IN THAT FILE.
Do NOT combine data from other files. For example, if 3.119.4-unreleased.md has 4 PRs
and 3.119.4.md has 101 PRs, the unreleased file should only cover those 4 PRs — it is
NOT a rollup of the version file.
Follow these rules:
Highlights — 1-3 sentences. What's the story? Lead with the biggest changes. Mention community contributors by linked name.
Skia engine — If a "Bump skia" or "milestone" PR appears in the raw data, list it first under an Engine category.
Categorize features — Group by what they affect. Use sub-headers: Engine, GPU & Rendering, API Surface, Text & Fonts, Platform, Security, etc. Each item: bold title — description. ❤️ @contributor (#NNN)
Community contributors — Anyone not @mattleibow. Mark with ❤️ inline AND
in a Contributors table. ALWAYS link: [@user](https://github.com/user).
Never write bare @user anywhere in the file.
Omit noise — Skip version bumps, CI-only fixes, doc updates, workflow/skill changes. If many, mention as: "Plus several CI and documentation improvements."
Breaking changes — If any, list under ### ⚠️ Breaking Changes after Highlights.
PR links — Every item links to its PR.
Generation timestamp — Always include <!-- Generated: YYYY-MM-DDTHH:MM:SSZ by {model-name} -->
as the first line AFTER the raw data comment block (before the # Version heading).
Use the current UTC time and your model name.
Rollup at top — Aggregate ALL changes across all previews into the main sections.
Previews are minimal — One sentence + changelog link each, at the bottom.
Links section — Full Changelog, NuGet Package, API Diff.
When regenerating multiple versions, process them in parallel — each version is independent. Fetch all raw data in one script call, then launch one agent per version to write the polished page.