Skip to content

Commit 46ee44c

Browse files
artl93jeffhandley
andauthored
Add libraries release-notes-generator Copilot skill (#10244)
* WIP - Add release notes generator and related documentation * Update default output path to release-notes/11.0/preview/preview1/libraries.md * Rename skill from release-notes-generator to libraries-release-notes * Add API Diff analysis as Step 1 of the workflow * Add backing issue research and Copilot comment fetching to the workflow * Add de-duplication against previous release notes * Update date range input to use Code Complete date guidance * Refine discovery and editorial instructions * Recognize multi-faceted PRs * Restructure skill into data/verify/author phases with independent steps * Improve libraries-release-notes skill to reduce approval prompts - Use SQL tool for intermediate data instead of writing .cache/ files - Remove disk I/O from gh CLI fallback instructions - Allow incremental input collection with progress tracking - Prohibit running linters, formatters, or validators on output * Use label-scoped searches to avoid large MCP responses - Add 'Avoid large MCP responses' execution guideline explaining that large search payloads get saved to temp files, requiring shell commands (and approval prompts) to read back. - Rewrite PR collection strategy to search per area label with small perPage values instead of fetching all merged PRs at once. - Prescribe view tool as fallback for any temp files instead of PowerShell commands. * Undo .gitignore cache addition for the libraries-release-notes skill * Refactor SKILL.md: extract inputs to reference file, relocate guidelines, remove workflow.md --------- Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
1 parent 4c6611d commit 46ee44c

File tree

10 files changed

+597
-0
lines changed

10 files changed

+597
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
name: libraries-release-notes
3+
description: Generate .NET Libraries release notes by evaluating the release's API diff, fetching merged PRs from a GitHub repository, categorizing by area or theme, and producing formatted markdown with exact benchmark data and code examples.
4+
disable-model-invocation: true
5+
argument-hint: "[owner/repo]"
6+
---
7+
8+
# Release Notes Generator
9+
10+
Generate .NET Libraries release notes for a given release.
11+
12+
## Execution guidelines
13+
14+
- **Do not write intermediate files to disk.** Use the **SQL tool** for structured storage and querying (see [data-2-collect-prs.md](references/data-2-collect-prs.md) for schema).
15+
- **Do not run linters, formatters, or validators.** Do not run markdownlint, prettier, link checkers, or any other validation tool on the output. The only output of this skill is the release notes markdown file itself.
16+
- **Maximize parallel tool calls.** Fetch multiple PR and issue details in a single response to minimize round trips.
17+
18+
## Process
19+
20+
1. **[Process Inputs and Validate Readiness](references/process-inputs.md)** — collect inputs and verify API diffs are available.
21+
2. **Data pipeline** — gather the changes included in the release:
22+
1. [Analyze the API diff](references/data-1-apidiff-review.md)
23+
2. [Collect and filter PRs](references/data-2-collect-prs.md)
24+
3. [Enrich — fetch PR and issue details](references/data-3-enrich.md)
25+
3. **Verify scope** — validate the candidate list:
26+
1. [Deduplicate from previous release notes](references/verify-1-dedupe.md)
27+
2. [Confirm inclusion in release branch](references/verify-2-release.md)
28+
4. **Author content** — write the release notes:
29+
1. [Categorize entries by area, theme, and impact](references/author-1-entries.md)
30+
2. [Apply formatting rules](references/author-2-format.md)
31+
3. [Apply editorial rules](references/author-3-editorial.md)
32+
5. Confirm feature list with the user before finalizing.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Author: Categorize by Area, Theme, and Impact
2+
3+
Group PRs into tiers:
4+
- **Headline features**: New namespaces or types, implementations of new industry trends/algorithms, major new API surfaces
5+
- **Quality**: PRs or groups of PRs that improve quality across an area (recognizing `area-*` labels on the PRs and issues)
6+
- **Performance**: PRs with benchmark data showing measurable improvements
7+
- **API additions**: New methods/overloads on existing types
8+
- **Small improvements**: Single-mapping additions, minor fixes with public API changes
9+
- **Community contributions**: Large PRs labeled as `community-contribution` or collections of such PRs by the same author
10+
11+
**Multi-faceted PRs.** A single PR may span multiple categories — for example, a PR that rewrites an implementation may improve correctness, fix bugs, simplify the codebase, *and* deliver performance gains. Do not reduce such PRs to a single category. When writing the release notes entry, describe the full scope of the improvement. A PR that fixes correctness bugs and improves performance should lead with the quality/reliability story and include performance data as supporting evidence — not be categorized as "Performance" alone. Read the full PR description, not just benchmark tables.
12+
13+
Only Headline, Quality, Performance, and significant API additions go into the release notes. Use judgment — a 2-line dictionary entry addition is less noteworthy than a new numeric type. The early previews (preview1 through preview5) tend to include more features, and the later previews (preview6, preview7, and rc1) tend to have fewer headline features and more quality improvements and small additions. The RC2 and GA releases typically have fewer changes so quality and performance improvements can be emphasized more.
14+
15+
For community contributions, if a community contributor has provided valuable features or quality improvements for popular libraries, give those entries more consideration for mentioning in the release notes.
16+
17+
Some example sets of release notes to use for reference and inspiration:
18+
* `release-notes/11.0/preview/preview1/libraries.md`
19+
* `release-notes/10.0/preview/preview1/libraries.md`
20+
* `release-notes/9.0/preview/rc1/libraries.md`
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Release Notes Format Template
2+
3+
The release notes must mirror the style of the official .NET Preview release notes (e.g. `.NET 10 Preview 1`).
4+
5+
## Document Structure
6+
7+
```markdown
8+
# .NET Libraries in .NET <VERSION> <PREVIEW> - Release Notes
9+
10+
.NET <VERSION> <PREVIEW> includes new .NET Libraries features & enhancements:
11+
12+
- [Feature Name](#anchor)
13+
- [Feature Name](#anchor)
14+
...
15+
16+
.NET Libraries updates in .NET <VERSION>:
17+
18+
- [What's new in .NET <VERSION>](https://learn.microsoft.com/dotnet/core/whats-new/dotnet-<version>/overview) documentation
19+
20+
## Feature Name
21+
22+
[<owner>/<repo> #NNNNN](https://github.com/<owner>/<repo>/pull/NNNNN) <one-paragraph description>.
23+
24+
```csharp
25+
// Code example or API signature
26+
```
27+
```
28+
29+
## Section Rules
30+
31+
1. **TOC at top** — Every feature gets a linked entry in the table of contents.
32+
2. **PR link first** — Each section opens with a link to the PR.
33+
3. **One paragraph of context** — What the feature does and why it matters.
34+
4. **API signature** — Show the new public API surface in a `csharp` code block.
35+
5. **Usage example** — A short, runnable code snippet showing the feature in action.
36+
6. **Benchmark summary** (if applicable) — State what was measured and the speedup range. Do NOT embed full BenchmarkDotNet tables.
37+
38+
## Example Section
39+
40+
```markdown
41+
## Finding Certificates By Thumbprints Other Than SHA-1
42+
43+
[<owner>/<repo> #NNNNN](https://github.com/<owner>/<repo>/pull/NNNNN) introduces a new method
44+
that accepts the name of the hash algorithm to use for matching, since SHA-2-256 and SHA-3-256
45+
have the same lengths and making the Find method match any vaguely matching thumbprint was not ideal.
46+
47+
\```csharp
48+
X509Certificate2Collection coll = store.Certificates.FindByThumbprint(
49+
HashAlgorithmName.SHA256, thumbprint);
50+
return coll.SingleOrDefault();
51+
\```
52+
```
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Editorial Rules
2+
3+
## Benchmarks
4+
5+
- Use **exact data** from PR descriptions — never round, approximate, or paraphrase performance numbers.
6+
- State the benchmark scenarios (what was measured, what hardware, what workloads).
7+
- Report speedup ranges (e.g. "2.4–3.9x faster on Windows, 1.6–4.7x on Linux").
8+
- Include specific before/after measurements when they tell a compelling story (e.g. "dropped from 48.0 ns to 12.2 ns").
9+
- Do **not** embed full BenchmarkDotNet tables in the release notes — summarize in prose.
10+
- If the user asks for exact tables, pull them verbatim from the PR body. Never reconstruct or approximate.
11+
12+
## Attribution
13+
14+
- **Community contributors**: If the PR author is not a Microsoft employee or a bot, cite them: `contributed by community member @handle`.
15+
- **Copilot-authored PRs**: The PR author will be `Copilot` (bot). Do not credit Copilot. Cite the assignee who merged it if attribution is needed.
16+
- **Microsoft employees**: No special attribution needed — they are implied.
17+
- When in doubt, check the PR author's GitHub profile or the `author_association` field (`MEMBER` = Microsoft, `CONTRIBUTOR`/`NONE` = community).
18+
19+
## Entry Naming
20+
21+
- Prefer a **brief description** of what the feature does over simply stating the API name. The heading should help a reader understand the value at a glance.
22+
-`## Support for Zstandard compression`
23+
-`## Faster time zone conversions`
24+
-`## Dictionary expression support for immutable and frozen collections`
25+
-`## ZstandardStream`
26+
-`## TimeZoneInfo performance`
27+
-`## ImmutableDictionary.CreateRange`
28+
- Keep headings concise — aim for 3–8 words.
29+
- Include the API or type name in the body text, not necessarily in the heading.
30+
31+
## Feature Ranking
32+
33+
Order features by **customer impact**, using both qualitative "wow" factor and quantitative popularity signals. Promote entries that affect popular, widely-used libraries; move niche or specialized scenarios lower.
34+
35+
**Primary ordering criteria** (biggest impact first):
36+
1. Major new capabilities for popular libraries (new types, new compression algorithms, new protocol support) — especially those with high reaction counts on the backing issue or PR
37+
2. Performance improvements with dramatic numbers in widely-used APIs (e.g. `DateTime.Now`, `HttpClient`, `JsonSerializer`)
38+
3. New API surfaces on popular existing types, prioritized by combined PR + issue reaction count
39+
4. Improvements to less-common or specialized libraries (e.g. `System.Reflection.Emit`, `System.Formats.Tar`)
40+
5. Small additions and fixes
41+
42+
**Popularity signals** (gathered in Step 5):
43+
- **Reaction counts**: PRs and issues with many 👍, ❤️, or 🚀 reactions indicate strong community demand. Use the combined reaction count across the PR and its linked issues as a tiebreaker within each tier.
44+
- **Linked issue upvotes**: An `api-approved` issue with 50+ reactions is a stronger signal than one with 2.
45+
- **Library popularity**: Changes to `System.Text.Json`, `System.Net.Http`, `System.Collections`, `System.IO`, and `System.Threading` affect more users than changes to narrower namespaces. When two entries are otherwise similar in impact, prefer the one in the more widely-used library.
46+
47+
## Inclusion Criteria
48+
49+
Include a feature if it meets ANY of:
50+
- Introduces a new public type or namespace
51+
- Adds significant new API surface (3+ new methods) to an existing type
52+
- Has benchmark data showing ≥20% improvement in a common scenario
53+
- Enables a scenario that was previously impossible or required workarounds
54+
- Was a highly-requested community feature (check linked issues for upvote counts)
55+
56+
Exclude:
57+
- Internal refactoring with no public API change
58+
- Test-only changes
59+
- Build/infrastructure changes
60+
- Backports from servicing branches
61+
- Single-line fixes unless they unblock a major scenario
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Step 1: Analyze API Diff
2+
3+
> **Note:** The [early API diff check](../SKILL.md#early-api-diff-check) in SKILL.md verifies that both the current and previous release API diffs exist *before* the data pipeline starts. By the time this step executes, the user has already been warned about any missing diffs and has chosen to proceed. If a diff is missing, skip the corresponding load step below but continue with the rest of the pipeline.
4+
5+
## Locate the API diff
6+
7+
Locate and load the `Microsoft.NETCore.App` API diff for the target release. The API diff provides context about which APIs were added or changed and significantly improves the quality of the generated release notes.
8+
9+
The API diff lives under the `release-notes` folder within an `api-diff` subfolder for the target release. For example:
10+
* .NET 10 RC 2: `release-notes/10.0/preview/rc2/api-diff/Microsoft.NETCore.App/10.0-RC2.md`
11+
* .NET 10 GA: `release-notes/10.0/preview/ga/api-diff/Microsoft.NETCore.App/10.0-ga.md`
12+
* .NET 11 Preview 1: `release-notes/11.0/preview/preview1/api-diff/Microsoft.NETCore.App/11.0-preview1.md`
13+
14+
## Load the API diff
15+
16+
Once the `api-diff` folder is located, load all of the API difference files under the `Microsoft.NETCore.App` subfolder:
17+
18+
```
19+
api-diff/Microsoft.NETCore.App/
20+
```
21+
22+
For example:
23+
24+
```
25+
release-notes/11.0/preview/preview1/api-diff/Microsoft.NETCore.App/
26+
```
27+
28+
Read every diff file in this folder to understand the full set of APIs that have been added or changed in the release. This information is used later to cross-reference with merged PRs and ensure the release notes accurately cover all API surface changes.
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# Step 2: Collect and Filter PRs
2+
3+
## MCP response size
4+
5+
GitHub MCP search tools that return large payloads get saved to temporary files on disk — reading those files back requires PowerShell commands that trigger approval prompts. Prevent this by keeping individual search result sets small:
6+
7+
- Use **label-scoped searches** (e.g. `label:area-System.Text.Json`) instead of fetching all merged PRs at once.
8+
- Use `perPage: 30` or less for search queries. Only use `perPage: 100` for targeted queries that are expected to return few results.
9+
- If a search response is saved to a temp file anyway, use the `view` tool (with `view_range` for large files) to read it — **never** use PowerShell/shell commands to read or parse these files.
10+
11+
## Fetch Merged PRs
12+
13+
Pull merged PRs in the date range from the specified repository, filtered to library areas. The primary method is the **GitHub MCP server** tools; fall back to the **GitHub CLI (`gh`)** if the MCP server is unavailable.
14+
15+
### Primary — GitHub MCP server
16+
17+
Use `search_pull_requests` with **label-scoped queries** to keep result sets small and avoid large responses being saved to temp files on disk (which then require shell commands to read — triggering approval prompts).
18+
19+
Search for merged PRs one area label at a time. The most common library area labels are listed below, but also search with the broader `label:area-System.` prefix to catch less-common areas:
20+
21+
```
22+
# Search per area label — one query per label, small result sets
23+
search_pull_requests(
24+
owner: "dotnet",
25+
repo: "runtime",
26+
query: "is:merged merged:2026-01-26..2026-02-11 label:area-System.Text.Json",
27+
perPage: 30
28+
)
29+
```
30+
31+
**Recommended area labels to search** (run these in parallel batches):
32+
33+
- `area-System.Text.Json`, `area-System.Net.Http`, `area-System.Collections`
34+
- `area-System.IO`, `area-System.IO.Compression`, `area-System.Threading`
35+
- `area-System.Numerics`, `area-System.Runtime`, `area-System.Memory`
36+
- `area-System.Security`, `area-System.Diagnostics`, `area-System.Globalization`
37+
- `area-System.Linq`, `area-System.Reflection`, `area-System.Reflection.Emit`
38+
- `area-System.Formats.*`, `area-System.Net.*`, `area-System.Text.*`
39+
- `area-Microsoft.Extensions.*`, `area-Extensions-*`
40+
41+
After the label-scoped searches, do a **catch-all search** for any remaining library PRs that may use uncommon area labels. Use a broad query but keep `perPage` small:
42+
43+
```
44+
search_pull_requests(
45+
owner: "dotnet",
46+
repo: "runtime",
47+
query: "is:merged merged:2026-01-26..2026-02-11 label:area-System",
48+
perPage: 30
49+
)
50+
```
51+
52+
Page through results (incrementing `page`) until all PRs for each query are collected. Deduplicate by PR number across all queries before inserting into the database.
53+
54+
**PRs without area labels.** Some PRs lack an `area-*` label altogether. To catch these, also run a search without label filters but restricted to a short date range and `perPage: 30`. Check the title and description of unlabeled PRs for library-relevant content. If a PR references a library issue (via "Fixes #..." links), fetch the issue to check for `area-*` labels.
55+
56+
### Fallback — GitHub CLI
57+
58+
If the GitHub MCP server is not available, use the `gh` CLI instead. Verify availability with `gh --version` first.
59+
60+
```bash
61+
REPO="dotnet/runtime" # Set from user input
62+
63+
# First batch (newer half of range)
64+
gh pr list --repo "$REPO" --state merged \
65+
--search "merged:2025-12-01..2026-02-01" \
66+
--limit 1000 --json number,title,labels,author,mergedAt,url
67+
68+
# Second batch (older half of range)
69+
gh pr list --repo "$REPO" --state merged \
70+
--search "merged:2025-10-01..2025-12-01" \
71+
--limit 1000 --json number,title,labels,author,mergedAt,url
72+
```
73+
74+
### Data storage
75+
76+
Store all fetched PR data using the **SQL tool**. Do **not** write cache files to disk — disk I/O triggers approval prompts. Insert each PR into the `prs` table and use SQL queries for all subsequent filtering.
77+
78+
```sql
79+
CREATE TABLE prs (
80+
number INTEGER PRIMARY KEY,
81+
title TEXT,
82+
author TEXT,
83+
author_association TEXT,
84+
labels TEXT, -- comma-separated label names
85+
merged_at TEXT,
86+
body TEXT,
87+
reactions INTEGER DEFAULT 0,
88+
is_library INTEGER DEFAULT 0,
89+
is_candidate INTEGER DEFAULT 0
90+
);
91+
92+
CREATE TABLE issues (
93+
number INTEGER PRIMARY KEY,
94+
title TEXT,
95+
body TEXT,
96+
labels TEXT,
97+
reactions INTEGER DEFAULT 0,
98+
pr_number INTEGER -- the PR that references this issue
99+
);
100+
```
101+
102+
Additional PRs can be added to the candidate list manually by number. Use [Enrich](data-3-enrich.md) to fetch their details.
103+
104+
## Filter to Library PRs
105+
106+
Since the search queries above are already scoped to library area labels, most results will be relevant. Apply these additional filters before marking PRs as candidates:
107+
108+
### Exclusion filters
109+
- Labels: `backport`, `servicing`, `NO-MERGE`
110+
- PRs whose title starts with `[release/` or contains `backport`
111+
- PRs that are purely test, CI, or documentation changes (no `src` changes)
112+
113+
### Cross-reference with API diff
114+
115+
If the API diff was loaded in [Step 1](data-1-apidiff-review.md), cross-reference the candidate PRs against the new APIs. For each new API or namespace in the diff, verify that at least one candidate PR covers it. If an API in the diff has **no matching PR**, search for the implementing PR explicitly:
116+
117+
```
118+
search_pull_requests(
119+
owner: "dotnet",
120+
repo: "runtime",
121+
query: "is:merged <API name or type name>"
122+
)
123+
```
124+
125+
This catches PRs that were missed by the date range (merged slightly after the Code Complete date but before the release branch was cut) or that lacked a recognized area label. Add any discovered PRs to the candidate list.
126+
127+
Also use the API diff to discover **issues** that drove new APIs. Many approved APIs originate from `api-approved` issues that may reference a broader feature story. Use `search_issues` to find related issues:
128+
129+
```
130+
search_issues(
131+
owner: "dotnet",
132+
repo: "runtime",
133+
query: "label:api-approved <API name or type name>"
134+
)
135+
```
136+
137+
If such issues exist, trace them to their implementing PRs and ensure those PRs are in the candidate list.
138+
139+
**Unmatched API surface area.** After cross-referencing, if any substantial new APIs in the diff still cannot be correlated to a PR or issue, include a placeholder section in the release notes for each unmatched API group. Use a `**TODO**` marker so the author can manually resolve it later. For example:
140+
141+
```markdown
142+
## <New API or Feature Name>
143+
144+
**TODO:** The API diff shows new surface area for `<Namespace.TypeName>` but the implementing PR/issue could not be found. Investigate and fill in this section.
145+
```
146+
147+
Mark matching PRs as candidates in the SQL `prs` table (`is_candidate = 1`).

0 commit comments

Comments
 (0)