From 73da1dab1c27508db67a1eb3f7aba73d18ab3169 Mon Sep 17 00:00:00 2001 From: artl Date: Mon, 9 Feb 2026 12:02:56 -0800 Subject: [PATCH 01/14] WIP - Add release notes generator and related documentation --- .../skills/release-notes-generator/SKILL.md | 27 +++++++ .../references/editorial-rules.md | 41 +++++++++++ .../references/format-template.md | 52 +++++++++++++ .../references/workflow.md | 73 +++++++++++++++++++ .gitignore | 3 + 5 files changed, 196 insertions(+) create mode 100644 .github/skills/release-notes-generator/SKILL.md create mode 100644 .github/skills/release-notes-generator/references/editorial-rules.md create mode 100644 .github/skills/release-notes-generator/references/format-template.md create mode 100644 .github/skills/release-notes-generator/references/workflow.md diff --git a/.github/skills/release-notes-generator/SKILL.md b/.github/skills/release-notes-generator/SKILL.md new file mode 100644 index 00000000000..dbc8262f4f9 --- /dev/null +++ b/.github/skills/release-notes-generator/SKILL.md @@ -0,0 +1,27 @@ +--- +name: release-notes-generator +description: Generate library preview release notes by fetching merged PRs from a GitHub repository, categorizing by impact, and producing formatted markdown with exact benchmark data and code examples. +disable-model-invocation: true +argument-hint: "[owner/repo]" +--- + +# Release Notes Generator + +Generate library release notes for a given preview period. + +## Inputs + +If `$ARGUMENTS` is provided, use `$0` as the repository. Otherwise ask the user for: +1. **Repository** — GitHub `owner/repo` to pull PRs from (e.g. `dotnet/runtime`) + +Then ask for: +2. **Preview name** (e.g. ".NET 11 Preview 1") +3. **Date range** — start and end dates for merged PRs (ISO 8601, e.g. `2025-10-01..2026-02-01`) +4. **Output file** — path for the release notes markdown (default: `LIBRARY_RELEASE_NOTES.md` at repo root) + +## Process + +1. Follow the [data pipeline](references/workflow.md) to fetch, cache, and filter PRs. +2. Follow the [formatting rules](references/format-template.md) to write the document. +3. Follow the [editorial rules](references/editorial-rules.md) for benchmarks, attribution, and ranking. +4. Confirm feature list with the user before finalizing. diff --git a/.github/skills/release-notes-generator/references/editorial-rules.md b/.github/skills/release-notes-generator/references/editorial-rules.md new file mode 100644 index 00000000000..64f64c832fb --- /dev/null +++ b/.github/skills/release-notes-generator/references/editorial-rules.md @@ -0,0 +1,41 @@ +# Editorial Rules + +## Benchmarks + +- Use **exact data** from PR descriptions — never round, approximate, or paraphrase performance numbers. +- State the benchmark scenarios (what was measured, what hardware, what workloads). +- Report speedup ranges (e.g. "2.4–3.9x faster on Windows, 1.6–4.7x on Linux"). +- Include specific before/after measurements when they tell a compelling story (e.g. "dropped from 48.0 ns to 12.2 ns"). +- Do **not** embed full BenchmarkDotNet tables in the release notes — summarize in prose. +- If the user asks for exact tables, pull them verbatim from the PR body. Never reconstruct or approximate. + +## Attribution + +- **Community contributors**: If the PR author is not a Microsoft employee or a bot, cite them: `contributed by community member @handle`. +- **Copilot-authored PRs**: The PR author will be `Copilot` (bot). Do not credit Copilot. Cite the assignee who merged it if attribution is needed. +- **Microsoft employees**: No special attribution needed — they are implied. +- When in doubt, check the PR author's GitHub profile or the `author_association` field (`MEMBER` = Microsoft, `CONTRIBUTOR`/`NONE` = community). + +## Feature Ranking + +Order features by **customer impact** ("wow" factor), biggest first: +1. Major new capabilities (new types, new compression algorithms, new protocol support) +2. Performance improvements with dramatic numbers +3. New API surfaces on existing types +4. Small additions and fixes + +## Inclusion Criteria + +Include a feature if it meets ANY of: +- Introduces a new public type or namespace +- Adds significant new API surface (3+ new methods) to an existing type +- Has benchmark data showing ≥20% improvement in a common scenario +- Enables a scenario that was previously impossible or required workarounds +- Was a highly-requested community feature (check linked issues for upvote counts) + +Exclude: +- Internal refactoring with no public API change +- Test-only changes +- Build/infrastructure changes +- Backports from servicing branches +- Single-line fixes unless they unblock a major scenario diff --git a/.github/skills/release-notes-generator/references/format-template.md b/.github/skills/release-notes-generator/references/format-template.md new file mode 100644 index 00000000000..b826724e1f4 --- /dev/null +++ b/.github/skills/release-notes-generator/references/format-template.md @@ -0,0 +1,52 @@ +# Release Notes Format Template + +The release notes must mirror the style of the official .NET Preview release notes (e.g. `.NET 10 Preview 1`). + +## Document Structure + +```markdown +# .NET Libraries in .NET - Release Notes + +.NET includes new .NET Libraries features & enhancements: + +- [Feature Name](#anchor) +- [Feature Name](#anchor) +... + +.NET Libraries updates in .NET : + +- [What's new in .NET ](https://learn.microsoft.com/dotnet/core/whats-new/dotnet-/overview) documentation + +## Feature Name + +[/ #NNNNN](https://github.com///pull/NNNNN) . + +```csharp +// Code example or API signature +``` +``` + +## Section Rules + +1. **TOC at top** — Every feature gets a linked entry in the table of contents. +2. **PR link first** — Each section opens with a link to the PR. +3. **One paragraph of context** — What the feature does and why it matters. +4. **API signature** — Show the new public API surface in a `csharp` code block. +5. **Usage example** — A short, runnable code snippet showing the feature in action. +6. **Benchmark summary** (if applicable) — State what was measured and the speedup range. Do NOT embed full BenchmarkDotNet tables. + +## Example Section + +```markdown +## Finding Certificates By Thumbprints Other Than SHA-1 + +[/ #NNNNN](https://github.com///pull/NNNNN) introduces a new method +that accepts the name of the hash algorithm to use for matching, since SHA-2-256 and SHA-3-256 +have the same lengths and making the Find method match any vaguely matching thumbprint was not ideal. + +\```csharp +X509Certificate2Collection coll = store.Certificates.FindByThumbprint( + HashAlgorithmName.SHA256, thumbprint); +return coll.SingleOrDefault(); +\``` +``` diff --git a/.github/skills/release-notes-generator/references/workflow.md b/.github/skills/release-notes-generator/references/workflow.md new file mode 100644 index 00000000000..fe64bc17276 --- /dev/null +++ b/.github/skills/release-notes-generator/references/workflow.md @@ -0,0 +1,73 @@ +# Data Pipeline — Fetching and Caching PRs + +## Step 1: Fetch Merged PRs + +Use the GitHub CLI to pull all merged PRs in the date range from the specified repository. The API returns a max of 1000 results per query, so split into batches if needed. + +Cache files are stored under `.cache///` so multiple repositories can be cached side-by-side without collision. + +```bash +REPO="dotnet/runtime" # Set from user input +CACHE_DIR=".cache/${REPO}" +mkdir -p "$CACHE_DIR" + +# First batch (newer half of range) +gh pr list --repo "$REPO" --state merged \ + --search "merged:2025-12-01..2026-02-01" \ + --limit 1000 --json number,title,labels,author,mergedAt,url \ + > "$CACHE_DIR/batch1.json" + +# Second batch (older half of range) +gh pr list --repo "$REPO" --state merged \ + --search "merged:2025-10-01..2025-12-01" \ + --limit 1000 --json number,title,labels,author,mergedAt,url \ + > "$CACHE_DIR/batch2.json" +``` + +Merge batches into `$CACHE_DIR/all_merged_prs.json`. This is the authoritative cached dataset — all subsequent steps read from cache. + +## Step 2: Filter to Library PRs + +From the merged set, keep only PRs where: +- At least one label starts with `area-System.` or `area-Microsoft.Extensions.` or `area-Meta` +- Exclude labels: `backport`, `servicing`, `NO-MERGE` +- Exclude PRs whose title starts with `[release/` or contains `backport` + +Save to `$CACHE_DIR/library_prs.json`. + +## Step 3: Fetch Detailed PR Bodies + +For each library PR, fetch the full body (description) which contains benchmark data, API signatures, and motivation: + +```bash +gh pr view --repo "$REPO" \ + --json number,title,body,labels,author,assignees,mergedAt,url +``` + +Cache results in `$CACHE_DIR/pr_details.json` (map of PR number → full detail object). This avoids re-fetching on subsequent runs. + +## Step 4: Categorize by Impact + +Group PRs into tiers: +- **Headline features**: New types, new compression algorithms, major new API surfaces +- **Performance**: PRs with benchmark data showing measurable improvements +- **API additions**: New methods/overloads on existing types +- **Small improvements**: Single-mapping additions, minor fixes with public API changes + +Only Headline, 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. + +## Cache Directory Structure + +``` +.cache/ +└── / + └── / + ├── all_merged_prs.json # Raw merged PR list + ├── batch1.json # First date range batch + ├── batch2.json # Second date range batch + ├── library_prs.json # Filtered to library-area PRs + ├── pr_details.json # Full PR bodies keyed by number + └── coauthors.txt # Copilot PR → assignee mapping +``` + +Always check if cache files exist before re-fetching. Only re-fetch if the user asks to refresh or the date range changes. diff --git a/.gitignore b/.gitignore index 5bbb800fddc..04fa0dc412e 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,6 @@ msbuild.wrn node_modules/ package-lock.json package.json + +# Release notes generator cache +.cache/ From 416539c62cf34368ed49e77dcf2b8859aa60786b Mon Sep 17 00:00:00 2001 From: artl Date: Mon, 9 Feb 2026 12:17:10 -0800 Subject: [PATCH 02/14] Update default output path to release-notes/11.0/preview/preview1/libraries.md --- .github/skills/release-notes-generator/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/skills/release-notes-generator/SKILL.md b/.github/skills/release-notes-generator/SKILL.md index dbc8262f4f9..45788535578 100644 --- a/.github/skills/release-notes-generator/SKILL.md +++ b/.github/skills/release-notes-generator/SKILL.md @@ -17,7 +17,7 @@ If `$ARGUMENTS` is provided, use `$0` as the repository. Otherwise ask the user Then ask for: 2. **Preview name** (e.g. ".NET 11 Preview 1") 3. **Date range** — start and end dates for merged PRs (ISO 8601, e.g. `2025-10-01..2026-02-01`) -4. **Output file** — path for the release notes markdown (default: `LIBRARY_RELEASE_NOTES.md` at repo root) +4. **Output file** — path for the release notes markdown (default: `release-notes/11.0/preview/preview1/libraries.md`) ## Process From fc31df816ad0d0a43e512c3d80b860307812f51b Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 03:02:42 -0800 Subject: [PATCH 03/14] Rename skill from release-notes-generator to libraries-release-notes --- .../SKILL.md | 2 +- .../references/editorial-rules.md | 0 .../references/format-template.md | 0 .../references/workflow.md | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename .github/skills/{release-notes-generator => libraries-release-notes}/SKILL.md (97%) rename .github/skills/{release-notes-generator => libraries-release-notes}/references/editorial-rules.md (100%) rename .github/skills/{release-notes-generator => libraries-release-notes}/references/format-template.md (100%) rename .github/skills/{release-notes-generator => libraries-release-notes}/references/workflow.md (100%) diff --git a/.github/skills/release-notes-generator/SKILL.md b/.github/skills/libraries-release-notes/SKILL.md similarity index 97% rename from .github/skills/release-notes-generator/SKILL.md rename to .github/skills/libraries-release-notes/SKILL.md index 45788535578..f021cda0d7d 100644 --- a/.github/skills/release-notes-generator/SKILL.md +++ b/.github/skills/libraries-release-notes/SKILL.md @@ -1,5 +1,5 @@ --- -name: release-notes-generator +name: libraries-release-notes description: Generate library preview release notes by fetching merged PRs from a GitHub repository, categorizing by impact, and producing formatted markdown with exact benchmark data and code examples. disable-model-invocation: true argument-hint: "[owner/repo]" diff --git a/.github/skills/release-notes-generator/references/editorial-rules.md b/.github/skills/libraries-release-notes/references/editorial-rules.md similarity index 100% rename from .github/skills/release-notes-generator/references/editorial-rules.md rename to .github/skills/libraries-release-notes/references/editorial-rules.md diff --git a/.github/skills/release-notes-generator/references/format-template.md b/.github/skills/libraries-release-notes/references/format-template.md similarity index 100% rename from .github/skills/release-notes-generator/references/format-template.md rename to .github/skills/libraries-release-notes/references/format-template.md diff --git a/.github/skills/release-notes-generator/references/workflow.md b/.github/skills/libraries-release-notes/references/workflow.md similarity index 100% rename from .github/skills/release-notes-generator/references/workflow.md rename to .github/skills/libraries-release-notes/references/workflow.md From 18f170f1f1cd58e4dd312ff2a56077b7229db128 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 03:03:45 -0800 Subject: [PATCH 04/14] Add API Diff analysis as Step 1 of the workflow --- .../skills/libraries-release-notes/SKILL.md | 6 +-- .../references/workflow.md | 39 ++++++++++++++++--- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/.github/skills/libraries-release-notes/SKILL.md b/.github/skills/libraries-release-notes/SKILL.md index f021cda0d7d..6b7ee400925 100644 --- a/.github/skills/libraries-release-notes/SKILL.md +++ b/.github/skills/libraries-release-notes/SKILL.md @@ -1,13 +1,13 @@ --- name: libraries-release-notes -description: Generate library preview release notes by fetching merged PRs from a GitHub repository, categorizing by impact, and producing formatted markdown with exact benchmark data and code examples. +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. disable-model-invocation: true argument-hint: "[owner/repo]" --- # Release Notes Generator -Generate library release notes for a given preview period. +Generate .NET Libraries release notes for a given release. ## Inputs @@ -21,7 +21,7 @@ Then ask for: ## Process -1. Follow the [data pipeline](references/workflow.md) to fetch, cache, and filter PRs. +1. Follow the [data pipeline](references/workflow.md) to fetch, cache, and filter the API diff, pull requests, and backing issues. 2. Follow the [formatting rules](references/format-template.md) to write the document. 3. Follow the [editorial rules](references/editorial-rules.md) for benchmarks, attribution, and ranking. 4. Confirm feature list with the user before finalizing. diff --git a/.github/skills/libraries-release-notes/references/workflow.md b/.github/skills/libraries-release-notes/references/workflow.md index fe64bc17276..7e868a04432 100644 --- a/.github/skills/libraries-release-notes/references/workflow.md +++ b/.github/skills/libraries-release-notes/references/workflow.md @@ -1,6 +1,35 @@ -# Data Pipeline — Fetching and Caching PRs +# Data Pipeline — Gathering the changes included in the release -## Step 1: Fetch Merged PRs +## Step 1: Analyze API Diff + +### 1a. Locate the API diff + +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. + +The API diff lives under the `release-notes` folder within an `api-diff` subfolder for the target release. For example: +* .NET 10 RC 2: `release-notes/10.0/preview/rc2/api-diff/Microsoft.NETCore.App/10.0-RC2.md` +* .NET 10 GA: `release-notes/10.0/preview/ga/api-diff/Microsoft.NETCore.App/10.0-ga.md` +* .NET 11 Preview 1: `release-notes/11.0/preview/preview1/api-diff/Microsoft.NETCore.App/11.0-preview1.md` + +Check the `release-notes/` folder in the current repository clone for the API diff. If it is not present locally, **warn the user** that the release notes generation gains substantial context from the API diff and suggest generating release notes after the API diff is ready. The user may choose to proceed without it, but quality will be reduced. + +### 1b. Load the API diff + +Once the `api-diff` folder is located, load all of the API difference files under the `Microsoft.NETCore.App` subfolder: + +``` +api-diff/Microsoft.NETCore.App/ +``` + +For example: + +``` +release-notes/11.0/preview/preview1/api-diff/Microsoft.NETCore.App/ +``` + +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. + +## Step 2: Fetch Merged PRs Use the GitHub CLI to pull all merged PRs in the date range from the specified repository. The API returns a max of 1000 results per query, so split into batches if needed. @@ -26,7 +55,7 @@ gh pr list --repo "$REPO" --state merged \ Merge batches into `$CACHE_DIR/all_merged_prs.json`. This is the authoritative cached dataset — all subsequent steps read from cache. -## Step 2: Filter to Library PRs +## Step 3: Filter to Library PRs From the merged set, keep only PRs where: - At least one label starts with `area-System.` or `area-Microsoft.Extensions.` or `area-Meta` @@ -35,7 +64,7 @@ From the merged set, keep only PRs where: Save to `$CACHE_DIR/library_prs.json`. -## Step 3: Fetch Detailed PR Bodies +## Step 4: Fetch Detailed PR Bodies For each library PR, fetch the full body (description) which contains benchmark data, API signatures, and motivation: @@ -46,7 +75,7 @@ gh pr view --repo "$REPO" \ Cache results in `$CACHE_DIR/pr_details.json` (map of PR number → full detail object). This avoids re-fetching on subsequent runs. -## Step 4: Categorize by Impact +## Step 5: Categorize by Impact Group PRs into tiers: - **Headline features**: New types, new compression algorithms, major new API surfaces From 3db4341e0bc5b9b25f59642b31cf775fb2d1665f Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 03:05:03 -0800 Subject: [PATCH 05/14] Add backing issue research and Copilot comment fetching to the workflow --- .../references/workflow.md | 155 ++++++++++++++++-- 1 file changed, 145 insertions(+), 10 deletions(-) diff --git a/.github/skills/libraries-release-notes/references/workflow.md b/.github/skills/libraries-release-notes/references/workflow.md index 7e868a04432..9c69d8ff8b1 100644 --- a/.github/skills/libraries-release-notes/references/workflow.md +++ b/.github/skills/libraries-release-notes/references/workflow.md @@ -31,9 +31,26 @@ Read every diff file in this folder to understand the full set of APIs that have ## Step 2: Fetch Merged PRs -Use the GitHub CLI to pull all merged PRs in the date range from the specified repository. The API returns a max of 1000 results per query, so split into batches if needed. +Pull all merged PRs in the date range from the specified repository. The primary method is the **GitHub MCP server** tools; fall back to the **GitHub CLI (`gh`)** if the MCP server is unavailable. -Cache files are stored under `.cache///` so multiple repositories can be cached side-by-side without collision. +### 2a. Primary — GitHub MCP server + +Use `search_pull_requests` to query for merged PRs. Split the date range into batches if needed to stay within query result limits. + +``` +search_pull_requests( + owner: "dotnet", + repo: "runtime", + query: "is:merged merged:2025-12-01..2026-02-01", + perPage: 100 +) +``` + +Page through results (incrementing `page`) until all PRs are collected. Repeat with subsequent date range batches as needed until all PRs from the date range have been collected. + +### 2b. Fallback — GitHub CLI + +If the GitHub MCP server is not available, use the `gh` CLI instead. Verify availability with `gh --version` first. ```bash REPO="dotnet/runtime" # Set from user input @@ -53,37 +70,154 @@ gh pr list --repo "$REPO" --state merged \ > "$CACHE_DIR/batch2.json" ``` -Merge batches into `$CACHE_DIR/all_merged_prs.json`. This is the authoritative cached dataset — all subsequent steps read from cache. +### Caching + +Regardless of which method is used, cache files are stored under `.cache///` so multiple repositories can be cached side-by-side without collision. Merge batches into `$CACHE_DIR/all_merged_prs.json`. This is the authoritative cached dataset — all subsequent steps read from cache. ## Step 3: Filter to Library PRs From the merged set, keep only PRs where: -- At least one label starts with `area-System.` or `area-Microsoft.Extensions.` or `area-Meta` +- Files modifying `System.*` or `Microsoft.Extensions.*` APIs (either `ref` or `src` changes) - Exclude labels: `backport`, `servicing`, `NO-MERGE` - Exclude PRs whose title starts with `[release/` or contains `backport` Save to `$CACHE_DIR/library_prs.json`. -## Step 4: Fetch Detailed PR Bodies +## Step 4: Fetch Pull Request and Related Issue Details + +For each library PR, fetch the full body (description) which contains benchmark data, API signatures, and motivation. Building on the PR data, fetch the details for issues referenced by or linked to the pull request — especially any issues resolved by the PR. Issues labeled `api-approved` represent new APIs being added and should be represented in the API diff if it was loaded. The issue often has a more detailed description than the PR, including API usage examples and a statement of impact/value. The final API shape (and usage example) might be somewhat out of date compared to what was approved and merged in the pull request, so usage examples may need to be revised. + +### 4a. Fetch PR details — GitHub MCP server (primary) + +Use `pull_request_read` with method `get` to fetch each PR's full details: + +``` +pull_request_read( + method: "get", + owner: "dotnet", + repo: "runtime", + pullNumber: +) +``` + +Multiple independent PR reads can be issued in parallel for efficiency. + +After fetching PR details, also fetch the PR's comments to look for **Copilot-generated summaries**. Copilot often posts a comment on PRs that summarizes the changes, intent, and impact — this can provide a concise understanding of the PR that complements the (sometimes lengthy or template-heavy) PR description. + +``` +pull_request_read( + method: "get_comments", + owner: "dotnet", + repo: "runtime", + pullNumber: +) +``` + +Look for comments authored by `copilot[bot]` or `github-actions[bot]` that contain a summary of the PR. These summaries are especially useful for large PRs where the description is auto-generated or sparse. Use this information to better understand the PR's purpose, but always cross-reference with the actual code changes and PR description for accuracy. + +### 4b. Discover related issues from the PR + +There are two complementary ways to find issues that a PR resolves or references. Use both to build a complete picture. + +#### 4b-i. Parse the PR description for issue links + +Scan the PR body text for issue references. Common patterns include: + +- **Closing keywords**: `Fixes #1234`, `Closes #1234`, `Resolves #1234` (GitHub auto-links these) +- **Full URL links**: `https://github.com/dotnet/runtime/issues/1234` +- **Cross-repo references**: `dotnet/runtime#1234` +- **Bare hash references**: `#1234` (relative to the PR's repository) + +Extract all unique issue numbers from these patterns. For Copilot-authored PRs, also look in the `
` / `Original prompt` collapsed section, which typically contains the original issue title, description, and a `Fixes` link at the bottom of the PR body. -For each library PR, fetch the full body (description) which contains benchmark data, API signatures, and motivation: +#### 4b-ii. Use the GitHub MCP server to find linked issues + +Use `search_issues` to find issues that reference the PR or that the PR resolves: + +``` +search_issues( + owner: "dotnet", + repo: "runtime", + query: "is:closed linked:pr reason:completed " +) +``` + +This can surface issues that were closed by the PR even if the PR description does not contain an explicit `Fixes` reference (e.g. when the link was added via the GitHub sidebar rather than the PR body). + +You can also search by API name or type to find the backing issue directly: + +``` +search_issues( + owner: "dotnet", + repo: "runtime", + query: "is:closed " +) +``` + +If any discovered issue carries the `api-approved` label, pay extra attention to both that issue and its associated PR. The `api-approved` issue typically contains the approved API shape, usage examples, motivation, and discussion from the API review — all of which are valuable background for writing compelling release notes. + +### 4c. Fetch issue details + +For each discovered issue number, use `issue_read` with method `get`: + +``` +issue_read( + method: "get", + owner: "dotnet", + repo: "runtime", + issue_number: +) +``` + +Multiple independent issue reads can be issued in parallel for efficiency. Prioritize fetching issues that are: + +- Referenced by a `Fixes`/`Closes`/`Resolves` keyword (these are the resolved issues) +- Labeled `api-approved` (these contain the approved API shape and usage examples) +- Labeled `enhancement` with high reaction counts (these indicate community demand) + +The issue body often contains richer context than the PR, including: +- **API proposals** with `### API Proposal` and `### API Usage` sections +- **Motivation** explaining why the feature was requested +- **Upvote counts** (via reactions) that indicate community demand +- **Discussion comments** that may contain approved API shapes from API review + +### 4d. Fallback — GitHub CLI + +If the GitHub MCP server is not available, use the `gh` CLI: ```bash gh pr view --repo "$REPO" \ --json number,title,body,labels,author,assignees,mergedAt,url + +gh issue view --repo "$REPO" \ + --json number,title,body,labels,author,assignees,url ``` -Cache results in `$CACHE_DIR/pr_details.json` (map of PR number → full detail object). This avoids re-fetching on subsequent runs. +To find issues closed by a PR via the CLI: + +```bash +# Search for closed issues linked to the PR +gh search issues --repo "$REPO" --state closed "linked:pr " +``` -## Step 5: Categorize by Impact +## Step 5: Categorize by Area/Theme/Impact Group PRs into tiers: -- **Headline features**: New types, new compression algorithms, major new API surfaces +- **Headline features**: New namespaces or types, implementations of new industry trends/algorithms, major new API surfaces +- **Quality**: PRs or groups of PRs that improve quality across an area (recognizing `area-*` labels on the PRs and issues) - **Performance**: PRs with benchmark data showing measurable improvements - **API additions**: New methods/overloads on existing types - **Small improvements**: Single-mapping additions, minor fixes with public API changes +- **Community contributions**: Large PRs labeled as `community-contribution` or collections of such PRs by the same author + +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. + +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. -Only Headline, 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. +Some example sets of release notes to use for reference and inspiration: +* `release-notes/11.0/preview/preview1/libraries.md` +* `release-notes/10.0/preview/preview1/libraries.md` +* `release-notes/9.0/preview/rc1/libraries.md` ## Cache Directory Structure @@ -96,6 +230,7 @@ Only Headline, Performance, and significant API additions go into the release no ├── batch2.json # Second date range batch ├── library_prs.json # Filtered to library-area PRs ├── pr_details.json # Full PR bodies keyed by number + ├── issue_details.json # Full issue bodies keyed by number └── coauthors.txt # Copilot PR → assignee mapping ``` From f9a8787465b3498e4284b570fe83305be4898a53 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 03:05:58 -0800 Subject: [PATCH 06/14] Add de-duplication against previous release notes --- .../references/workflow.md | 50 ++++++++++++++++--- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/.github/skills/libraries-release-notes/references/workflow.md b/.github/skills/libraries-release-notes/references/workflow.md index 9c69d8ff8b1..448ea6969ef 100644 --- a/.github/skills/libraries-release-notes/references/workflow.md +++ b/.github/skills/libraries-release-notes/references/workflow.md @@ -83,11 +83,45 @@ From the merged set, keep only PRs where: Save to `$CACHE_DIR/library_prs.json`. -## Step 4: Fetch Pull Request and Related Issue Details +## Step 4: Deduplicate Against Previous Release Notes + +Before fetching full PR details, check that candidate features have not already been covered in an earlier preview's release notes for the same major version. + +### 4a. Load prior release notes + +Load the `libraries.md` file from the immediately preceding release within the same major version. For example, when generating Preview 3, load Preview 2's notes; when generating RC1, load Preview 7's notes. + +When generating **Preview 1** release notes for a new major version, there are no prior previews to check. Instead, look back at the prior major version's late-cycle release notes — specifically RC1, RC2, and GA — since features that landed late in the previous release cycle may overlap with early work in the new version. For example, when generating .NET 12 Preview 1 notes, check: + +``` +release-notes/11.0/preview/rc1/libraries.md +release-notes/11.0/preview/rc2/libraries.md +release-notes/11.0/preview/ga/libraries.md +``` + +These files are in the local repository clone under `release-notes//preview/`. + +### 4b. Check for overlap + +For each candidate PR, check whether it (or its feature) already appears in a prior release's notes by looking for: + +- **PR number references** — search for `#` or the full PR URL in prior files +- **Feature names** — search for the API name, type name, or feature title (e.g. `IdnMapping`, `File.OpenNullHandle`, `Zstandard`) + +Remove any PR from the candidate list whose feature is already covered. A PR that was merged in the date range of a prior preview but was not included in that preview's release notes may still be included — only exclude PRs whose features were actually written up. + +### 4c. Handle cross-preview features + +Some features span multiple PRs across previews (e.g. a Preview 1 PR adds the core API and a Preview 2 PR extends it). In these cases: + +- If the Preview 2 PR is a **substantial extension** (new overloads, new scenarios, significant perf improvement on top of the original, or breaking changes to the API shape), include it as an update referencing the earlier work. +- If the Preview 2 PR is a **minor follow-up** (bug fix, test addition, doc comment), skip it. + +## Step 5: Fetch Pull Request and Related Issue Details For each library PR, fetch the full body (description) which contains benchmark data, API signatures, and motivation. Building on the PR data, fetch the details for issues referenced by or linked to the pull request — especially any issues resolved by the PR. Issues labeled `api-approved` represent new APIs being added and should be represented in the API diff if it was loaded. The issue often has a more detailed description than the PR, including API usage examples and a statement of impact/value. The final API shape (and usage example) might be somewhat out of date compared to what was approved and merged in the pull request, so usage examples may need to be revised. -### 4a. Fetch PR details — GitHub MCP server (primary) +### 5a. Fetch PR details — GitHub MCP server (primary) Use `pull_request_read` with method `get` to fetch each PR's full details: @@ -115,11 +149,11 @@ pull_request_read( Look for comments authored by `copilot[bot]` or `github-actions[bot]` that contain a summary of the PR. These summaries are especially useful for large PRs where the description is auto-generated or sparse. Use this information to better understand the PR's purpose, but always cross-reference with the actual code changes and PR description for accuracy. -### 4b. Discover related issues from the PR +### 5b. Discover related issues from the PR There are two complementary ways to find issues that a PR resolves or references. Use both to build a complete picture. -#### 4b-i. Parse the PR description for issue links +#### 5b-i. Parse the PR description for issue links Scan the PR body text for issue references. Common patterns include: @@ -130,7 +164,7 @@ Scan the PR body text for issue references. Common patterns include: Extract all unique issue numbers from these patterns. For Copilot-authored PRs, also look in the `
` / `Original prompt` collapsed section, which typically contains the original issue title, description, and a `Fixes` link at the bottom of the PR body. -#### 4b-ii. Use the GitHub MCP server to find linked issues +#### 5b-ii. Use the GitHub MCP server to find linked issues Use `search_issues` to find issues that reference the PR or that the PR resolves: @@ -156,7 +190,7 @@ search_issues( If any discovered issue carries the `api-approved` label, pay extra attention to both that issue and its associated PR. The `api-approved` issue typically contains the approved API shape, usage examples, motivation, and discussion from the API review — all of which are valuable background for writing compelling release notes. -### 4c. Fetch issue details +### 5c. Fetch issue details For each discovered issue number, use `issue_read` with method `get`: @@ -181,7 +215,7 @@ The issue body often contains richer context than the PR, including: - **Upvote counts** (via reactions) that indicate community demand - **Discussion comments** that may contain approved API shapes from API review -### 4d. Fallback — GitHub CLI +### 5d. Fallback — GitHub CLI If the GitHub MCP server is not available, use the `gh` CLI: @@ -200,7 +234,7 @@ To find issues closed by a PR via the CLI: gh search issues --repo "$REPO" --state closed "linked:pr " ``` -## Step 5: Categorize by Area/Theme/Impact +## Step 6: Categorize by Area/Theme/Impact Group PRs into tiers: - **Headline features**: New namespaces or types, implementations of new industry trends/algorithms, major new API surfaces From 7048d9e5db5e00ee4a10495076d61e1cd6a5e583 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 03:06:18 -0800 Subject: [PATCH 07/14] Update date range input to use Code Complete date guidance --- .github/skills/libraries-release-notes/SKILL.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/skills/libraries-release-notes/SKILL.md b/.github/skills/libraries-release-notes/SKILL.md index 6b7ee400925..1be35af0c81 100644 --- a/.github/skills/libraries-release-notes/SKILL.md +++ b/.github/skills/libraries-release-notes/SKILL.md @@ -16,7 +16,9 @@ If `$ARGUMENTS` is provided, use `$0` as the repository. Otherwise ask the user Then ask for: 2. **Preview name** (e.g. ".NET 11 Preview 1") -3. **Date range** — start and end dates for merged PRs (ISO 8601, e.g. `2025-10-01..2026-02-01`) +3. **Date range** — ask for the start and end dates separately using the .NET release calendar's "Code complete" milestones: + - **Start date**: Ask for the Code Complete date of the *previous* release. For example, when generating .NET 11 Preview 2 notes, ask: *"What is the Code Complete date for .NET 11 Preview 1? (ISO 8601, e.g. 2026-01-27)"*. When generating **Preview 1** notes, ask for the *previous major version's* RC1 Code Complete date instead (e.g. *"What is the Code Complete date for .NET 10 RC1?"*), since that is when the vNext fork occurs. Reassure the user that anything already covered in the prior version's RC1, RC2, or GA release notes will be de-duplicated in Step 4. + - **End date**: Ask for the Code Complete date of the *current* release. For example: *"What is the Code Complete date for .NET 11 Preview 1?"* 4. **Output file** — path for the release notes markdown (default: `release-notes/11.0/preview/preview1/libraries.md`) ## Process From 28b715c8cf60dbddbb5366d47b6e0005a0fbde9c Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 02:36:13 -0800 Subject: [PATCH 08/14] Refine discovery and editorial instructions --- .../references/editorial-rules.md | 30 ++++- .../references/workflow.md | 124 ++++++++++++++++-- 2 files changed, 140 insertions(+), 14 deletions(-) diff --git a/.github/skills/libraries-release-notes/references/editorial-rules.md b/.github/skills/libraries-release-notes/references/editorial-rules.md index 64f64c832fb..e176e026f6f 100644 --- a/.github/skills/libraries-release-notes/references/editorial-rules.md +++ b/.github/skills/libraries-release-notes/references/editorial-rules.md @@ -16,13 +16,33 @@ - **Microsoft employees**: No special attribution needed — they are implied. - When in doubt, check the PR author's GitHub profile or the `author_association` field (`MEMBER` = Microsoft, `CONTRIBUTOR`/`NONE` = community). +## Entry Naming + +- 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. + - ✅ `## Support for Zstandard compression` + - ✅ `## Faster time zone conversions` + - ✅ `## Dictionary expression support for immutable and frozen collections` + - ❌ `## ZstandardStream` + - ❌ `## TimeZoneInfo performance` + - ❌ `## ImmutableDictionary.CreateRange` +- Keep headings concise — aim for 3–8 words. +- Include the API or type name in the body text, not necessarily in the heading. + ## Feature Ranking -Order features by **customer impact** ("wow" factor), biggest first: -1. Major new capabilities (new types, new compression algorithms, new protocol support) -2. Performance improvements with dramatic numbers -3. New API surfaces on existing types -4. Small additions and fixes +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. + +**Primary ordering criteria** (biggest impact first): +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 +2. Performance improvements with dramatic numbers in widely-used APIs (e.g. `DateTime.Now`, `HttpClient`, `JsonSerializer`) +3. New API surfaces on popular existing types, prioritized by combined PR + issue reaction count +4. Improvements to less-common or specialized libraries (e.g. `System.Reflection.Emit`, `System.Formats.Tar`) +5. Small additions and fixes + +**Popularity signals** (gathered in Step 5): +- **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. +- **Linked issue upvotes**: An `api-approved` issue with 50+ reactions is a stronger signal than one with 2. +- **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. ## Inclusion Criteria diff --git a/.github/skills/libraries-release-notes/references/workflow.md b/.github/skills/libraries-release-notes/references/workflow.md index 448ea6969ef..ca7efd79b48 100644 --- a/.github/skills/libraries-release-notes/references/workflow.md +++ b/.github/skills/libraries-release-notes/references/workflow.md @@ -35,7 +35,7 @@ Pull all merged PRs in the date range from the specified repository. The primary ### 2a. Primary — GitHub MCP server -Use `search_pull_requests` to query for merged PRs. Split the date range into batches if needed to stay within query result limits. +Use `search_pull_requests` to query for merged PRs. The initial query should fetch **all** merged PRs in the date range without label filtering, to avoid missing PRs labeled with less-common area labels (e.g. `area-System.DateTime`, `area-System.Reflection.Emit`, `area-System.Globalization`). Split the date range into sub-ranges if needed to stay within GitHub's 1,000-result search limit. ``` search_pull_requests( @@ -46,7 +46,7 @@ search_pull_requests( ) ``` -Page through results (incrementing `page`) until all PRs are collected. Repeat with subsequent date range batches as needed until all PRs from the date range have been collected. +Page through results (incrementing `page`) until all PRs are collected. If a single date range returns close to 1,000 results, split into smaller sub-ranges (e.g. halve the range) and repeat. Do **not** restrict the initial search to specific area labels — label-based filtering happens later in Step 3. ### 2b. Fallback — GitHub CLI @@ -76,13 +76,108 @@ Regardless of which method is used, cache files are stored under `.cache/ ## Step 3: Filter to Library PRs -From the merged set, keep only PRs where: -- Files modifying `System.*` or `Microsoft.Extensions.*` APIs (either `ref` or `src` changes) -- Exclude labels: `backport`, `servicing`, `NO-MERGE` -- Exclude PRs whose title starts with `[release/` or contains `backport` +### 3a. Label-based filtering + +From the merged set, keep only PRs that have a label matching any `area-System.*`, `area-Microsoft.Extensions*`, or `area-Extensions-*` pattern. Match the label prefix broadly — do **not** use a hard-coded list of specific area labels, as that risks missing PRs labeled with less-common areas (e.g. `area-System.DateTime`, `area-System.Reflection.Emit`, `area-System.Globalization`). + +**PRs without area labels.** PR labels cannot be entirely trusted — some PRs lack an `area-*` label altogether. Do not discard these PRs immediately. Instead, check their linked or related issues (from the PR description's "Fixes #..." references) for `area-*` labels. If a related issue carries a matching `area-System.*`, `area-Microsoft.Extensions*`, or `area-Extensions-*` label, include the PR in the candidate list. + +Additionally exclude: +- Labels: `backport`, `servicing`, `NO-MERGE` +- PRs whose title starts with `[release/` or contains `backport` +- PRs that are purely test, CI, or documentation changes (no `src` changes) + +### 3b. Cross-reference with API diff + +If the API diff was loaded in Step 1, 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: + +``` +search_pull_requests( + owner: "dotnet", + repo: "runtime", + query: "is:merged " +) +``` + +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. + +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: + +``` +search_issues( + owner: "dotnet", + repo: "runtime", + query: "label:api-approved " +) +``` + +If such issues exist, trace them to their implementing PRs and ensure those PRs are in the candidate list. + +**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: + +```markdown +## + +**TODO:** The API diff shows new surface area for `` but the implementing PR/issue could not be found. Investigate and fill in this section. +``` Save to `$CACHE_DIR/library_prs.json`. +### 3c. Verify changes are present in the release branch + +After filtering, verify that candidate changes actually shipped in the target release by checking the `dotnet/dotnet` Virtual Monolithic Repository (VMR). The VMR contains all .NET source code — including `dotnet/runtime` under `src/runtime/` — and its release branches represent what ships in each preview. + +**Determine the release branch name.** The expected branch name pattern is: + +``` +release/.0.1xx- +``` + +For example: +- .NET 11 Preview 1 → `release/11.0.1xx-preview1` +- .NET 11 Preview 2 → `release/11.0.1xx-preview2` +- .NET 11 RC 1 → `release/11.0.1xx-rc1` + +Use the GitHub MCP server (or CLI fallback) to verify the branch exists: + +``` +list_branches( + owner: "dotnet", + repo: "dotnet" +) +``` + +If the expected branch is **not found**, search for branches matching `release/.0*` and present the user with the matching branch names so they can select the correct one. + +**Spot-check that the newest changes are included.** Start from the most recently merged PRs in the candidate list and work backward. For each PR, verify its changes are present in the VMR release branch by either: + +1. **Searching for code** introduced by the PR in the `dotnet/dotnet` repo: + + ``` + search_code( + query: "repo:dotnet/dotnet path:src/runtime " + ) + ``` + +2. **Checking commit history** on the release branch for runtime source code updates that post-date the PR merge: + + ``` + list_commits( + owner: "dotnet", + repo: "dotnet", + sha: "release/.0.1xx-", + perPage: 30 + ) + ``` + + Look for commits with messages like `"Source code updates from dotnet/runtime"` dated after the PR's merge date. The dotnet-maestro bot regularly syncs changes from `dotnet/runtime` into the VMR. + +Stop checking after **2 consecutive PRs are confirmed present** — if the two newest changes made it into the release branch, older changes are also included. + +If any change is **not found** in the release branch, inform the user that the feature may not have been included in this preview release. Suggest either: +- Moving that feature to the **next preview's** release notes +- Confirming with the release team whether a late sync occurred + ## Step 4: Deduplicate Against Previous Release Notes Before fetching full PR details, check that candidate features have not already been covered in an earlier preview's release notes for the same major version. @@ -110,7 +205,18 @@ For each candidate PR, check whether it (or its feature) already appears in a pr Remove any PR from the candidate list whose feature is already covered. A PR that was merged in the date range of a prior preview but was not included in that preview's release notes may still be included — only exclude PRs whose features were actually written up. -### 4c. Handle cross-preview features +### 4c. Flag earlier PRs that survived dedup + +If any PRs were removed during dedup, review the remaining candidate PRs that were merged **before** the previous release's Code Complete date (i.e. PRs whose merge date falls in the earlier portion of the date range). These PRs were not found in the prior release notes but their merge dates suggest they *could* have been covered elsewhere. Present these PRs to the user and ask whether each should be included or excluded. For example: + +> The following PRs were merged before the .NET 11 Preview 1 Code Complete date but were **not** found in any prior release notes. They may have been intentionally omitted or covered in a different document. Please confirm whether to include them: +> +> - #12345 — `Add Foo.Bar overload` (merged 2025-11-15) +> - #12400 — `Optimize Baz serialization` (merged 2025-12-03) + +If no PRs were removed during dedup (i.e. nothing overlapped with prior notes), skip this sub-step — the earlier merge dates are expected given the date range and do not need user confirmation. + +### 4d. Handle cross-preview features Some features span multiple PRs across previews (e.g. a Preview 1 PR adds the core API and a Preview 2 PR extends it). In these cases: @@ -134,7 +240,7 @@ pull_request_read( ) ``` -Multiple independent PR reads can be issued in parallel for efficiency. +Multiple independent PR reads can be issued in parallel for efficiency. The PR response includes a `reactions` object with counts for each reaction type (e.g. `+1`, `heart`, `rocket`). Record the **total reaction count** for each PR as a popularity signal — PRs with high reaction counts indicate strong community interest. After fetching PR details, also fetch the PR's comments to look for **Copilot-generated summaries**. Copilot often posts a comment on PRs that summarizes the changes, intent, and impact — this can provide a concise understanding of the PR that complements the (sometimes lengthy or template-heavy) PR description. @@ -203,7 +309,7 @@ issue_read( ) ``` -Multiple independent issue reads can be issued in parallel for efficiency. Prioritize fetching issues that are: +Multiple independent issue reads can be issued in parallel for efficiency. The issue response includes a `reactions` object — record the **total reaction count** for each issue. Combine the PR and issue reaction counts to form an overall **popularity score** for each feature (sum of all `+1`, `heart`, `rocket`, and other positive reactions across the PR and its linked issues). Prioritize fetching issues that are: - Referenced by a `Fixes`/`Closes`/`Resolves` keyword (these are the resolved issues) - Labeled `api-approved` (these contain the approved API shape and usage examples) From d064a9202df77e089ecf9aa80835b6aa6909cab0 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 02:54:02 -0800 Subject: [PATCH 09/14] Recognize multi-faceted PRs --- .github/skills/libraries-release-notes/references/workflow.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/skills/libraries-release-notes/references/workflow.md b/.github/skills/libraries-release-notes/references/workflow.md index ca7efd79b48..c010be40476 100644 --- a/.github/skills/libraries-release-notes/references/workflow.md +++ b/.github/skills/libraries-release-notes/references/workflow.md @@ -350,6 +350,8 @@ Group PRs into tiers: - **Small improvements**: Single-mapping additions, minor fixes with public API changes - **Community contributions**: Large PRs labeled as `community-contribution` or collections of such PRs by the same author +**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. + 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. 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. From c0e948e07bfe73e889b2553f31f656ab9f1e8a97 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 03:37:45 -0800 Subject: [PATCH 10/14] Restructure skill into data/verify/author phases with independent steps --- .../skills/libraries-release-notes/SKILL.md | 16 +- .../references/author-1-entries.md | 20 + ...{format-template.md => author-2-format.md} | 0 ...itorial-rules.md => author-3-editorial.md} | 0 .../references/data-1-apidiff-review.md | 28 ++ .../references/data-2-collect-prs.md | 95 +++++ .../references/data-3-enrich.md | 116 ++++++ .../references/verify-1-dedupe.md | 44 +++ .../references/verify-2-release.md | 58 +++ .../references/workflow.md | 372 ++---------------- 10 files changed, 395 insertions(+), 354 deletions(-) create mode 100644 .github/skills/libraries-release-notes/references/author-1-entries.md rename .github/skills/libraries-release-notes/references/{format-template.md => author-2-format.md} (100%) rename .github/skills/libraries-release-notes/references/{editorial-rules.md => author-3-editorial.md} (100%) create mode 100644 .github/skills/libraries-release-notes/references/data-1-apidiff-review.md create mode 100644 .github/skills/libraries-release-notes/references/data-2-collect-prs.md create mode 100644 .github/skills/libraries-release-notes/references/data-3-enrich.md create mode 100644 .github/skills/libraries-release-notes/references/verify-1-dedupe.md create mode 100644 .github/skills/libraries-release-notes/references/verify-2-release.md diff --git a/.github/skills/libraries-release-notes/SKILL.md b/.github/skills/libraries-release-notes/SKILL.md index 1be35af0c81..8012a8938a7 100644 --- a/.github/skills/libraries-release-notes/SKILL.md +++ b/.github/skills/libraries-release-notes/SKILL.md @@ -17,13 +17,21 @@ If `$ARGUMENTS` is provided, use `$0` as the repository. Otherwise ask the user Then ask for: 2. **Preview name** (e.g. ".NET 11 Preview 1") 3. **Date range** — ask for the start and end dates separately using the .NET release calendar's "Code complete" milestones: - - **Start date**: Ask for the Code Complete date of the *previous* release. For example, when generating .NET 11 Preview 2 notes, ask: *"What is the Code Complete date for .NET 11 Preview 1? (ISO 8601, e.g. 2026-01-27)"*. When generating **Preview 1** notes, ask for the *previous major version's* RC1 Code Complete date instead (e.g. *"What is the Code Complete date for .NET 10 RC1?"*), since that is when the vNext fork occurs. Reassure the user that anything already covered in the prior version's RC1, RC2, or GA release notes will be de-duplicated in Step 4. + - **Start date**: Ask for the Code Complete date of the *previous* release. For example, when generating .NET 11 Preview 2 notes, ask: *"What is the Code Complete date for .NET 11 Preview 1? (ISO 8601, e.g. 2026-01-27)"*. When generating **Preview 1** notes, ask for the *previous major version's* RC1 Code Complete date instead (e.g. *"What is the Code Complete date for .NET 10 RC1?"*), since that is when the vNext fork occurs. Reassure the user that anything already covered in the prior version's RC1, RC2, or GA release notes will be de-duplicated in the [verify scope](references/verify-1-dedupe.md) step. - **End date**: Ask for the Code Complete date of the *current* release. For example: *"What is the Code Complete date for .NET 11 Preview 1?"* 4. **Output file** — path for the release notes markdown (default: `release-notes/11.0/preview/preview1/libraries.md`) ## Process -1. Follow the [data pipeline](references/workflow.md) to fetch, cache, and filter the API diff, pull requests, and backing issues. -2. Follow the [formatting rules](references/format-template.md) to write the document. -3. Follow the [editorial rules](references/editorial-rules.md) for benchmarks, attribution, and ranking. +1. **[Data pipeline](references/workflow.md)** — gather the changes included in the release: + 1. [Analyze the API diff](references/data-1-apidiff-review.md) + 2. [Collect and filter PRs](references/data-2-collect-prs.md) + 3. [Enrich — fetch PR and issue details](references/data-3-enrich.md) +2. **Verify scope** — validate the candidate list: + 1. [Deduplicate from previous release notes](references/verify-1-dedupe.md) + 2. [Confirm inclusion in release branch](references/verify-2-release.md) +3. **Author content** — write the release notes: + 1. [Categorize entries by area, theme, and impact](references/author-1-entries.md) + 2. [Apply formatting rules](references/author-2-format.md) + 3. [Apply editorial rules](references/author-3-editorial.md) 4. Confirm feature list with the user before finalizing. diff --git a/.github/skills/libraries-release-notes/references/author-1-entries.md b/.github/skills/libraries-release-notes/references/author-1-entries.md new file mode 100644 index 00000000000..c2a74047316 --- /dev/null +++ b/.github/skills/libraries-release-notes/references/author-1-entries.md @@ -0,0 +1,20 @@ +# Author: Categorize by Area, Theme, and Impact + +Group PRs into tiers: +- **Headline features**: New namespaces or types, implementations of new industry trends/algorithms, major new API surfaces +- **Quality**: PRs or groups of PRs that improve quality across an area (recognizing `area-*` labels on the PRs and issues) +- **Performance**: PRs with benchmark data showing measurable improvements +- **API additions**: New methods/overloads on existing types +- **Small improvements**: Single-mapping additions, minor fixes with public API changes +- **Community contributions**: Large PRs labeled as `community-contribution` or collections of such PRs by the same author + +**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. + +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. + +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. + +Some example sets of release notes to use for reference and inspiration: +* `release-notes/11.0/preview/preview1/libraries.md` +* `release-notes/10.0/preview/preview1/libraries.md` +* `release-notes/9.0/preview/rc1/libraries.md` diff --git a/.github/skills/libraries-release-notes/references/format-template.md b/.github/skills/libraries-release-notes/references/author-2-format.md similarity index 100% rename from .github/skills/libraries-release-notes/references/format-template.md rename to .github/skills/libraries-release-notes/references/author-2-format.md diff --git a/.github/skills/libraries-release-notes/references/editorial-rules.md b/.github/skills/libraries-release-notes/references/author-3-editorial.md similarity index 100% rename from .github/skills/libraries-release-notes/references/editorial-rules.md rename to .github/skills/libraries-release-notes/references/author-3-editorial.md diff --git a/.github/skills/libraries-release-notes/references/data-1-apidiff-review.md b/.github/skills/libraries-release-notes/references/data-1-apidiff-review.md new file mode 100644 index 00000000000..783951e5ef4 --- /dev/null +++ b/.github/skills/libraries-release-notes/references/data-1-apidiff-review.md @@ -0,0 +1,28 @@ +# Step 1: Analyze API Diff + +## Locate the API diff + +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. + +The API diff lives under the `release-notes` folder within an `api-diff` subfolder for the target release. For example: +* .NET 10 RC 2: `release-notes/10.0/preview/rc2/api-diff/Microsoft.NETCore.App/10.0-RC2.md` +* .NET 10 GA: `release-notes/10.0/preview/ga/api-diff/Microsoft.NETCore.App/10.0-ga.md` +* .NET 11 Preview 1: `release-notes/11.0/preview/preview1/api-diff/Microsoft.NETCore.App/11.0-preview1.md` + +Check the `release-notes/` folder in the current repository clone for the API diff. If it is not present locally, **warn the user** that the release notes generation gains substantial context from the API diff and suggest generating release notes after the API diff is ready. The user may choose to proceed without it, but quality will be reduced. + +## Load the API diff + +Once the `api-diff` folder is located, load all of the API difference files under the `Microsoft.NETCore.App` subfolder: + +``` +api-diff/Microsoft.NETCore.App/ +``` + +For example: + +``` +release-notes/11.0/preview/preview1/api-diff/Microsoft.NETCore.App/ +``` + +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. diff --git a/.github/skills/libraries-release-notes/references/data-2-collect-prs.md b/.github/skills/libraries-release-notes/references/data-2-collect-prs.md new file mode 100644 index 00000000000..b3f47982bbd --- /dev/null +++ b/.github/skills/libraries-release-notes/references/data-2-collect-prs.md @@ -0,0 +1,95 @@ +# Step 2: Collect and Filter PRs + +## Fetch Merged PRs + +Pull all merged PRs in the date range from the specified repository. The primary method is the **GitHub MCP server** tools; fall back to the **GitHub CLI (`gh`)** if the MCP server is unavailable. + +### Primary — GitHub MCP server + +Use `search_pull_requests` to query for merged PRs. The initial query should fetch **all** merged PRs in the date range without label filtering, to avoid missing PRs labeled with less-common area labels (e.g. `area-System.DateTime`, `area-System.Reflection.Emit`, `area-System.Globalization`). Split the date range into sub-ranges if needed to stay within GitHub's 1,000-result search limit. + +``` +search_pull_requests( + owner: "dotnet", + repo: "runtime", + query: "is:merged merged:2025-12-01..2026-02-01", + perPage: 100 +) +``` + +Page through results (incrementing `page`) until all PRs are collected. If a single date range returns close to 1,000 results, split into smaller sub-ranges (e.g. halve the range) and repeat. Do **not** restrict the initial search to specific area labels — label-based filtering happens later in the filtering step. + +### Fallback — GitHub CLI + +If the GitHub MCP server is not available, use the `gh` CLI instead. Verify availability with `gh --version` first. + +```bash +REPO="dotnet/runtime" # Set from user input +CACHE_DIR=".cache/${REPO}" +mkdir -p "$CACHE_DIR" + +# First batch (newer half of range) +gh pr list --repo "$REPO" --state merged \ + --search "merged:2025-12-01..2026-02-01" \ + --limit 1000 --json number,title,labels,author,mergedAt,url \ + > "$CACHE_DIR/batch1.json" + +# Second batch (older half of range) +gh pr list --repo "$REPO" --state merged \ + --search "merged:2025-10-01..2025-12-01" \ + --limit 1000 --json number,title,labels,author,mergedAt,url \ + > "$CACHE_DIR/batch2.json" +``` + +### Caching + +Regardless of which method is used, cache files are stored under `.cache///` so multiple repositories can be cached side-by-side without collision. Merge batches into `$CACHE_DIR/all_merged_prs.json`. This is the authoritative cached dataset — all subsequent steps read from cache. + +## Filter to Library PRs + +### Label-based filtering + +From the merged set, keep only PRs that have a label matching any `area-System.*`, `area-Microsoft.Extensions*`, or `area-Extensions-*` pattern. Match the label prefix broadly — do **not** use a hard-coded list of specific area labels, as that risks missing PRs labeled with less-common areas (e.g. `area-System.DateTime`, `area-System.Reflection.Emit`, `area-System.Globalization`). + +**PRs without area labels.** PR labels cannot be entirely trusted — some PRs lack an `area-*` label altogether. Do not discard these PRs immediately. Instead, check their linked or related issues (from the PR description's "Fixes #..." references) for `area-*` labels. If a related issue carries a matching `area-System.*`, `area-Microsoft.Extensions*`, or `area-Extensions-*` label, include the PR in the candidate list. + +Additionally exclude: +- Labels: `backport`, `servicing`, `NO-MERGE` +- PRs whose title starts with `[release/` or contains `backport` +- PRs that are purely test, CI, or documentation changes (no `src` changes) + +### Cross-reference with API diff + +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: + +``` +search_pull_requests( + owner: "dotnet", + repo: "runtime", + query: "is:merged " +) +``` + +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. + +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: + +``` +search_issues( + owner: "dotnet", + repo: "runtime", + query: "label:api-approved " +) +``` + +If such issues exist, trace them to their implementing PRs and ensure those PRs are in the candidate list. + +**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: + +```markdown +## + +**TODO:** The API diff shows new surface area for `` but the implementing PR/issue could not be found. Investigate and fill in this section. +``` + +Save to `$CACHE_DIR/library_prs.json`. diff --git a/.github/skills/libraries-release-notes/references/data-3-enrich.md b/.github/skills/libraries-release-notes/references/data-3-enrich.md new file mode 100644 index 00000000000..4b8438ad462 --- /dev/null +++ b/.github/skills/libraries-release-notes/references/data-3-enrich.md @@ -0,0 +1,116 @@ +# Step 4: Enrich — Fetch PR and Issue Details + +For each library PR, fetch the full body (description) which contains benchmark data, API signatures, and motivation. Building on the PR data, fetch the details for issues referenced by or linked to the pull request — especially any issues resolved by the PR. Issues labeled `api-approved` represent new APIs being added and should be represented in the API diff if it was loaded. The issue often has a more detailed description than the PR, including API usage examples and a statement of impact/value. The final API shape (and usage example) might be somewhat out of date compared to what was approved and merged in the pull request, so usage examples may need to be revised. + +## Fetch PR details — GitHub MCP server (primary) + +Use `pull_request_read` with method `get` to fetch each PR's full details: + +``` +pull_request_read( + method: "get", + owner: "dotnet", + repo: "runtime", + pullNumber: +) +``` + +Multiple independent PR reads can be issued in parallel for efficiency. The PR response includes a `reactions` object with counts for each reaction type (e.g. `+1`, `heart`, `rocket`). Record the **total reaction count** for each PR as a popularity signal — PRs with high reaction counts indicate strong community interest. + +After fetching PR details, also fetch the PR's comments to look for **Copilot-generated summaries**. Copilot often posts a comment on PRs that summarizes the changes, intent, and impact — this can provide a concise understanding of the PR that complements the (sometimes lengthy or template-heavy) PR description. + +``` +pull_request_read( + method: "get_comments", + owner: "dotnet", + repo: "runtime", + pullNumber: +) +``` + +Look for comments authored by `copilot[bot]` or `github-actions[bot]` that contain a summary of the PR. These summaries are especially useful for large PRs where the description is auto-generated or sparse. Use this information to better understand the PR's purpose, but always cross-reference with the actual code changes and PR description for accuracy. + +## Discover related issues from the PR + +There are two complementary ways to find issues that a PR resolves or references. Use both to build a complete picture. + +### Parse the PR description for issue links + +Scan the PR body text for issue references. Common patterns include: + +- **Closing keywords**: `Fixes #1234`, `Closes #1234`, `Resolves #1234` (GitHub auto-links these) +- **Full URL links**: `https://github.com/dotnet/runtime/issues/1234` +- **Cross-repo references**: `dotnet/runtime#1234` +- **Bare hash references**: `#1234` (relative to the PR's repository) + +Extract all unique issue numbers from these patterns. For Copilot-authored PRs, also look in the `
` / `Original prompt` collapsed section, which typically contains the original issue title, description, and a `Fixes` link at the bottom of the PR body. + +### Use the GitHub MCP server to find linked issues + +Use `search_issues` to find issues that reference the PR or that the PR resolves: + +``` +search_issues( + owner: "dotnet", + repo: "runtime", + query: "is:closed linked:pr reason:completed " +) +``` + +This can surface issues that were closed by the PR even if the PR description does not contain an explicit `Fixes` reference (e.g. when the link was added via the GitHub sidebar rather than the PR body). + +You can also search by API name or type to find the backing issue directly: + +``` +search_issues( + owner: "dotnet", + repo: "runtime", + query: "is:closed " +) +``` + +If any discovered issue carries the `api-approved` label, pay extra attention to both that issue and its associated PR. The `api-approved` issue typically contains the approved API shape, usage examples, motivation, and discussion from the API review — all of which are valuable background for writing compelling release notes. + +## Fetch issue details + +For each discovered issue number, use `issue_read` with method `get`: + +``` +issue_read( + method: "get", + owner: "dotnet", + repo: "runtime", + issue_number: +) +``` + +Multiple independent issue reads can be issued in parallel for efficiency. The issue response includes a `reactions` object — record the **total reaction count** for each issue. Combine the PR and issue reaction counts to form an overall **popularity score** for each feature (sum of all `+1`, `heart`, `rocket`, and other positive reactions across the PR and its linked issues). Prioritize fetching issues that are: + +- Referenced by a `Fixes`/`Closes`/`Resolves` keyword (these are the resolved issues) +- Labeled `api-approved` (these contain the approved API shape and usage examples) +- Labeled `enhancement` with high reaction counts (these indicate community demand) + +The issue body often contains richer context than the PR, including: +- **API proposals** with `### API Proposal` and `### API Usage` sections +- **Motivation** explaining why the feature was requested +- **Upvote counts** (via reactions) that indicate community demand +- **Discussion comments** that may contain approved API shapes from API review + +## Fallback — GitHub CLI + +If the GitHub MCP server is not available, use the `gh` CLI: + +```bash +gh pr view --repo "$REPO" \ + --json number,title,body,labels,author,assignees,mergedAt,url + +gh issue view --repo "$REPO" \ + --json number,title,body,labels,author,assignees,url +``` + +To find issues closed by a PR via the CLI: + +```bash +# Search for closed issues linked to the PR +gh search issues --repo "$REPO" --state closed "linked:pr " +``` diff --git a/.github/skills/libraries-release-notes/references/verify-1-dedupe.md b/.github/skills/libraries-release-notes/references/verify-1-dedupe.md new file mode 100644 index 00000000000..ce713645f89 --- /dev/null +++ b/.github/skills/libraries-release-notes/references/verify-1-dedupe.md @@ -0,0 +1,44 @@ +# Verify: Deduplicate Against Previous Release Notes + +Before authoring content, check that candidate features have not already been covered in an earlier preview's release notes for the same major version. + +## Load prior release notes + +Load the `libraries.md` file from the immediately preceding release within the same major version. For example, when generating Preview 3, load Preview 2's notes; when generating RC1, load Preview 7's notes. + +When generating **Preview 1** release notes for a new major version, there are no prior previews to check. Instead, look back at the prior major version's late-cycle release notes — specifically RC1, RC2, and GA — since features that landed late in the previous release cycle may overlap with early work in the new version. For example, when generating .NET 12 Preview 1 notes, check: + +``` +release-notes/11.0/preview/rc1/libraries.md +release-notes/11.0/preview/rc2/libraries.md +release-notes/11.0/preview/ga/libraries.md +``` + +These files are in the local repository clone under `release-notes//preview/`. + +## Check for overlap + +For each candidate PR, check whether it (or its feature) already appears in a prior release's notes by looking for: + +- **PR number references** — search for `#` or the full PR URL in prior files +- **Feature names** — search for the API name, type name, or feature title (e.g. `IdnMapping`, `File.OpenNullHandle`, `Zstandard`) + +Remove any PR from the candidate list whose feature is already covered. A PR that was merged in the date range of a prior preview but was not included in that preview's release notes may still be included — only exclude PRs whose features were actually written up. + +## Flag earlier PRs that survived dedup + +If any PRs were removed during dedup, review the remaining candidate PRs that were merged **before** the previous release's Code Complete date (i.e. PRs whose merge date falls in the earlier portion of the date range). These PRs were not found in the prior release notes but their merge dates suggest they *could* have been covered elsewhere. Present these PRs to the user and ask whether each should be included or excluded. For example: + +> The following PRs were merged before the .NET 11 Preview 1 Code Complete date but were **not** found in any prior release notes. They may have been intentionally omitted or covered in a different document. Please confirm whether to include them: +> +> - #12345 — `Add Foo.Bar overload` (merged 2025-11-15) +> - #12400 — `Optimize Baz serialization` (merged 2025-12-03) + +If no PRs were removed during dedup (i.e. nothing overlapped with prior notes), skip this sub-step — the earlier merge dates are expected given the date range and do not need user confirmation. + +## Handle cross-preview features + +Some features span multiple PRs across previews (e.g. a Preview 1 PR adds the core API and a Preview 2 PR extends it). In these cases: + +- If the Preview 2 PR is a **substantial extension** (new overloads, new scenarios, significant perf improvement on top of the original, or breaking changes to the API shape), include it as an update referencing the earlier work. +- If the Preview 2 PR is a **minor follow-up** (bug fix, test addition, doc comment), skip it. diff --git a/.github/skills/libraries-release-notes/references/verify-2-release.md b/.github/skills/libraries-release-notes/references/verify-2-release.md new file mode 100644 index 00000000000..d2bd8f5a600 --- /dev/null +++ b/.github/skills/libraries-release-notes/references/verify-2-release.md @@ -0,0 +1,58 @@ +# Verify: Confirm Inclusion in Release Branch + +After collecting and enriching candidates (including any manually added PRs), verify that candidate changes actually shipped in the target release by checking the `dotnet/dotnet` Virtual Monolithic Repository (VMR). The VMR contains all .NET source code — including `dotnet/runtime` under `src/runtime/` — and its release branches represent what ships in each preview. + +## Determine the release branch name + +The expected branch name pattern is: + +``` +release/.0.1xx- +``` + +For example: +- .NET 11 Preview 1 → `release/11.0.1xx-preview1` +- .NET 11 Preview 2 → `release/11.0.1xx-preview2` +- .NET 11 RC 1 → `release/11.0.1xx-rc1` + +Use the GitHub MCP server (or CLI fallback) to verify the branch exists: + +``` +list_branches( + owner: "dotnet", + repo: "dotnet" +) +``` + +If the expected branch is **not found**, search for branches matching `release/.0*` and present the user with the matching branch names so they can select the correct one. + +## Spot-check that the newest changes are included + +Start from the most recently merged PRs in the candidate list and work backward. For each PR, verify its changes are present in the VMR release branch by either: + +1. **Searching for code** introduced by the PR in the `dotnet/dotnet` repo: + + ``` + search_code( + query: "repo:dotnet/dotnet path:src/runtime " + ) + ``` + +2. **Checking commit history** on the release branch for runtime source code updates that post-date the PR merge: + + ``` + list_commits( + owner: "dotnet", + repo: "dotnet", + sha: "release/.0.1xx-", + perPage: 30 + ) + ``` + + Look for commits with messages like `"Source code updates from dotnet/runtime"` dated after the PR's merge date. The dotnet-maestro bot regularly syncs changes from `dotnet/runtime` into the VMR. + +Stop checking after **2 consecutive PRs are confirmed present** — if the two newest changes made it into the release branch, older changes are also included. + +If any change is **not found** in the release branch, inform the user that the feature may not have been included in this preview release. Suggest either: +- Moving that feature to the **next preview's** release notes +- Confirming with the release team whether a late sync occurred diff --git a/.github/skills/libraries-release-notes/references/workflow.md b/.github/skills/libraries-release-notes/references/workflow.md index c010be40476..65c615a6b23 100644 --- a/.github/skills/libraries-release-notes/references/workflow.md +++ b/.github/skills/libraries-release-notes/references/workflow.md @@ -1,365 +1,37 @@ # Data Pipeline — Gathering the changes included in the release -## Step 1: Analyze API Diff +This workflow orchestrates the full process for generating .NET Libraries release notes. Each step is documented in its own reference file and can be invoked independently. -### 1a. Locate the API diff +## Step 1: Data Pipeline -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. +Gather and enrich the candidate changes for the release. -The API diff lives under the `release-notes` folder within an `api-diff` subfolder for the target release. For example: -* .NET 10 RC 2: `release-notes/10.0/preview/rc2/api-diff/Microsoft.NETCore.App/10.0-RC2.md` -* .NET 10 GA: `release-notes/10.0/preview/ga/api-diff/Microsoft.NETCore.App/10.0-ga.md` -* .NET 11 Preview 1: `release-notes/11.0/preview/preview1/api-diff/Microsoft.NETCore.App/11.0-preview1.md` +| Step | Description | Reference | +|------|-------------|-----------| +| 1.1 | **Analyze API Diff** — Locate and load the API diff to understand new/changed APIs | [data-1-apidiff-review.md](data-1-apidiff-review.md) | +| 1.2 | **Collect & Filter PRs** — Fetch merged PRs, filter to library areas, cross-reference API diff | [data-2-collect-prs.md](data-2-collect-prs.md) | +| 1.3 | **Enrich** — Fetch full PR details, Copilot summaries, backing issues, and reaction counts | [data-3-enrich.md](data-3-enrich.md) | -Check the `release-notes/` folder in the current repository clone for the API diff. If it is not present locally, **warn the user** that the release notes generation gains substantial context from the API diff and suggest generating release notes after the API diff is ready. The user may choose to proceed without it, but quality will be reduced. +After Step 1.2, additional PRs can be added to the candidate list manually by number. Use Step 1.3 to fetch their details. -### 1b. Load the API diff +## Step 2: Verify Scope -Once the `api-diff` folder is located, load all of the API difference files under the `Microsoft.NETCore.App` subfolder: +Validate the candidate list before authoring content. These verification steps apply to all candidates, including any manually added PRs. -``` -api-diff/Microsoft.NETCore.App/ -``` - -For example: - -``` -release-notes/11.0/preview/preview1/api-diff/Microsoft.NETCore.App/ -``` - -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. - -## Step 2: Fetch Merged PRs - -Pull all merged PRs in the date range from the specified repository. The primary method is the **GitHub MCP server** tools; fall back to the **GitHub CLI (`gh`)** if the MCP server is unavailable. - -### 2a. Primary — GitHub MCP server - -Use `search_pull_requests` to query for merged PRs. The initial query should fetch **all** merged PRs in the date range without label filtering, to avoid missing PRs labeled with less-common area labels (e.g. `area-System.DateTime`, `area-System.Reflection.Emit`, `area-System.Globalization`). Split the date range into sub-ranges if needed to stay within GitHub's 1,000-result search limit. - -``` -search_pull_requests( - owner: "dotnet", - repo: "runtime", - query: "is:merged merged:2025-12-01..2026-02-01", - perPage: 100 -) -``` - -Page through results (incrementing `page`) until all PRs are collected. If a single date range returns close to 1,000 results, split into smaller sub-ranges (e.g. halve the range) and repeat. Do **not** restrict the initial search to specific area labels — label-based filtering happens later in Step 3. - -### 2b. Fallback — GitHub CLI - -If the GitHub MCP server is not available, use the `gh` CLI instead. Verify availability with `gh --version` first. - -```bash -REPO="dotnet/runtime" # Set from user input -CACHE_DIR=".cache/${REPO}" -mkdir -p "$CACHE_DIR" - -# First batch (newer half of range) -gh pr list --repo "$REPO" --state merged \ - --search "merged:2025-12-01..2026-02-01" \ - --limit 1000 --json number,title,labels,author,mergedAt,url \ - > "$CACHE_DIR/batch1.json" - -# Second batch (older half of range) -gh pr list --repo "$REPO" --state merged \ - --search "merged:2025-10-01..2025-12-01" \ - --limit 1000 --json number,title,labels,author,mergedAt,url \ - > "$CACHE_DIR/batch2.json" -``` - -### Caching - -Regardless of which method is used, cache files are stored under `.cache///` so multiple repositories can be cached side-by-side without collision. Merge batches into `$CACHE_DIR/all_merged_prs.json`. This is the authoritative cached dataset — all subsequent steps read from cache. - -## Step 3: Filter to Library PRs - -### 3a. Label-based filtering - -From the merged set, keep only PRs that have a label matching any `area-System.*`, `area-Microsoft.Extensions*`, or `area-Extensions-*` pattern. Match the label prefix broadly — do **not** use a hard-coded list of specific area labels, as that risks missing PRs labeled with less-common areas (e.g. `area-System.DateTime`, `area-System.Reflection.Emit`, `area-System.Globalization`). - -**PRs without area labels.** PR labels cannot be entirely trusted — some PRs lack an `area-*` label altogether. Do not discard these PRs immediately. Instead, check their linked or related issues (from the PR description's "Fixes #..." references) for `area-*` labels. If a related issue carries a matching `area-System.*`, `area-Microsoft.Extensions*`, or `area-Extensions-*` label, include the PR in the candidate list. - -Additionally exclude: -- Labels: `backport`, `servicing`, `NO-MERGE` -- PRs whose title starts with `[release/` or contains `backport` -- PRs that are purely test, CI, or documentation changes (no `src` changes) - -### 3b. Cross-reference with API diff - -If the API diff was loaded in Step 1, 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: - -``` -search_pull_requests( - owner: "dotnet", - repo: "runtime", - query: "is:merged " -) -``` - -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. - -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: - -``` -search_issues( - owner: "dotnet", - repo: "runtime", - query: "label:api-approved " -) -``` - -If such issues exist, trace them to their implementing PRs and ensure those PRs are in the candidate list. - -**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: - -```markdown -## - -**TODO:** The API diff shows new surface area for `` but the implementing PR/issue could not be found. Investigate and fill in this section. -``` - -Save to `$CACHE_DIR/library_prs.json`. - -### 3c. Verify changes are present in the release branch - -After filtering, verify that candidate changes actually shipped in the target release by checking the `dotnet/dotnet` Virtual Monolithic Repository (VMR). The VMR contains all .NET source code — including `dotnet/runtime` under `src/runtime/` — and its release branches represent what ships in each preview. - -**Determine the release branch name.** The expected branch name pattern is: - -``` -release/.0.1xx- -``` - -For example: -- .NET 11 Preview 1 → `release/11.0.1xx-preview1` -- .NET 11 Preview 2 → `release/11.0.1xx-preview2` -- .NET 11 RC 1 → `release/11.0.1xx-rc1` - -Use the GitHub MCP server (or CLI fallback) to verify the branch exists: - -``` -list_branches( - owner: "dotnet", - repo: "dotnet" -) -``` - -If the expected branch is **not found**, search for branches matching `release/.0*` and present the user with the matching branch names so they can select the correct one. - -**Spot-check that the newest changes are included.** Start from the most recently merged PRs in the candidate list and work backward. For each PR, verify its changes are present in the VMR release branch by either: - -1. **Searching for code** introduced by the PR in the `dotnet/dotnet` repo: - - ``` - search_code( - query: "repo:dotnet/dotnet path:src/runtime " - ) - ``` - -2. **Checking commit history** on the release branch for runtime source code updates that post-date the PR merge: - - ``` - list_commits( - owner: "dotnet", - repo: "dotnet", - sha: "release/.0.1xx-", - perPage: 30 - ) - ``` - - Look for commits with messages like `"Source code updates from dotnet/runtime"` dated after the PR's merge date. The dotnet-maestro bot regularly syncs changes from `dotnet/runtime` into the VMR. - -Stop checking after **2 consecutive PRs are confirmed present** — if the two newest changes made it into the release branch, older changes are also included. - -If any change is **not found** in the release branch, inform the user that the feature may not have been included in this preview release. Suggest either: -- Moving that feature to the **next preview's** release notes -- Confirming with the release team whether a late sync occurred - -## Step 4: Deduplicate Against Previous Release Notes - -Before fetching full PR details, check that candidate features have not already been covered in an earlier preview's release notes for the same major version. - -### 4a. Load prior release notes - -Load the `libraries.md` file from the immediately preceding release within the same major version. For example, when generating Preview 3, load Preview 2's notes; when generating RC1, load Preview 7's notes. - -When generating **Preview 1** release notes for a new major version, there are no prior previews to check. Instead, look back at the prior major version's late-cycle release notes — specifically RC1, RC2, and GA — since features that landed late in the previous release cycle may overlap with early work in the new version. For example, when generating .NET 12 Preview 1 notes, check: - -``` -release-notes/11.0/preview/rc1/libraries.md -release-notes/11.0/preview/rc2/libraries.md -release-notes/11.0/preview/ga/libraries.md -``` - -These files are in the local repository clone under `release-notes//preview/`. - -### 4b. Check for overlap - -For each candidate PR, check whether it (or its feature) already appears in a prior release's notes by looking for: - -- **PR number references** — search for `#` or the full PR URL in prior files -- **Feature names** — search for the API name, type name, or feature title (e.g. `IdnMapping`, `File.OpenNullHandle`, `Zstandard`) - -Remove any PR from the candidate list whose feature is already covered. A PR that was merged in the date range of a prior preview but was not included in that preview's release notes may still be included — only exclude PRs whose features were actually written up. - -### 4c. Flag earlier PRs that survived dedup - -If any PRs were removed during dedup, review the remaining candidate PRs that were merged **before** the previous release's Code Complete date (i.e. PRs whose merge date falls in the earlier portion of the date range). These PRs were not found in the prior release notes but their merge dates suggest they *could* have been covered elsewhere. Present these PRs to the user and ask whether each should be included or excluded. For example: - -> The following PRs were merged before the .NET 11 Preview 1 Code Complete date but were **not** found in any prior release notes. They may have been intentionally omitted or covered in a different document. Please confirm whether to include them: -> -> - #12345 — `Add Foo.Bar overload` (merged 2025-11-15) -> - #12400 — `Optimize Baz serialization` (merged 2025-12-03) - -If no PRs were removed during dedup (i.e. nothing overlapped with prior notes), skip this sub-step — the earlier merge dates are expected given the date range and do not need user confirmation. - -### 4d. Handle cross-preview features - -Some features span multiple PRs across previews (e.g. a Preview 1 PR adds the core API and a Preview 2 PR extends it). In these cases: - -- If the Preview 2 PR is a **substantial extension** (new overloads, new scenarios, significant perf improvement on top of the original, or breaking changes to the API shape), include it as an update referencing the earlier work. -- If the Preview 2 PR is a **minor follow-up** (bug fix, test addition, doc comment), skip it. - -## Step 5: Fetch Pull Request and Related Issue Details - -For each library PR, fetch the full body (description) which contains benchmark data, API signatures, and motivation. Building on the PR data, fetch the details for issues referenced by or linked to the pull request — especially any issues resolved by the PR. Issues labeled `api-approved` represent new APIs being added and should be represented in the API diff if it was loaded. The issue often has a more detailed description than the PR, including API usage examples and a statement of impact/value. The final API shape (and usage example) might be somewhat out of date compared to what was approved and merged in the pull request, so usage examples may need to be revised. - -### 5a. Fetch PR details — GitHub MCP server (primary) - -Use `pull_request_read` with method `get` to fetch each PR's full details: - -``` -pull_request_read( - method: "get", - owner: "dotnet", - repo: "runtime", - pullNumber: -) -``` - -Multiple independent PR reads can be issued in parallel for efficiency. The PR response includes a `reactions` object with counts for each reaction type (e.g. `+1`, `heart`, `rocket`). Record the **total reaction count** for each PR as a popularity signal — PRs with high reaction counts indicate strong community interest. - -After fetching PR details, also fetch the PR's comments to look for **Copilot-generated summaries**. Copilot often posts a comment on PRs that summarizes the changes, intent, and impact — this can provide a concise understanding of the PR that complements the (sometimes lengthy or template-heavy) PR description. - -``` -pull_request_read( - method: "get_comments", - owner: "dotnet", - repo: "runtime", - pullNumber: -) -``` - -Look for comments authored by `copilot[bot]` or `github-actions[bot]` that contain a summary of the PR. These summaries are especially useful for large PRs where the description is auto-generated or sparse. Use this information to better understand the PR's purpose, but always cross-reference with the actual code changes and PR description for accuracy. - -### 5b. Discover related issues from the PR - -There are two complementary ways to find issues that a PR resolves or references. Use both to build a complete picture. - -#### 5b-i. Parse the PR description for issue links - -Scan the PR body text for issue references. Common patterns include: - -- **Closing keywords**: `Fixes #1234`, `Closes #1234`, `Resolves #1234` (GitHub auto-links these) -- **Full URL links**: `https://github.com/dotnet/runtime/issues/1234` -- **Cross-repo references**: `dotnet/runtime#1234` -- **Bare hash references**: `#1234` (relative to the PR's repository) - -Extract all unique issue numbers from these patterns. For Copilot-authored PRs, also look in the `
` / `Original prompt` collapsed section, which typically contains the original issue title, description, and a `Fixes` link at the bottom of the PR body. - -#### 5b-ii. Use the GitHub MCP server to find linked issues - -Use `search_issues` to find issues that reference the PR or that the PR resolves: - -``` -search_issues( - owner: "dotnet", - repo: "runtime", - query: "is:closed linked:pr reason:completed " -) -``` - -This can surface issues that were closed by the PR even if the PR description does not contain an explicit `Fixes` reference (e.g. when the link was added via the GitHub sidebar rather than the PR body). - -You can also search by API name or type to find the backing issue directly: - -``` -search_issues( - owner: "dotnet", - repo: "runtime", - query: "is:closed " -) -``` - -If any discovered issue carries the `api-approved` label, pay extra attention to both that issue and its associated PR. The `api-approved` issue typically contains the approved API shape, usage examples, motivation, and discussion from the API review — all of which are valuable background for writing compelling release notes. - -### 5c. Fetch issue details - -For each discovered issue number, use `issue_read` with method `get`: - -``` -issue_read( - method: "get", - owner: "dotnet", - repo: "runtime", - issue_number: -) -``` - -Multiple independent issue reads can be issued in parallel for efficiency. The issue response includes a `reactions` object — record the **total reaction count** for each issue. Combine the PR and issue reaction counts to form an overall **popularity score** for each feature (sum of all `+1`, `heart`, `rocket`, and other positive reactions across the PR and its linked issues). Prioritize fetching issues that are: - -- Referenced by a `Fixes`/`Closes`/`Resolves` keyword (these are the resolved issues) -- Labeled `api-approved` (these contain the approved API shape and usage examples) -- Labeled `enhancement` with high reaction counts (these indicate community demand) - -The issue body often contains richer context than the PR, including: -- **API proposals** with `### API Proposal` and `### API Usage` sections -- **Motivation** explaining why the feature was requested -- **Upvote counts** (via reactions) that indicate community demand -- **Discussion comments** that may contain approved API shapes from API review - -### 5d. Fallback — GitHub CLI - -If the GitHub MCP server is not available, use the `gh` CLI: - -```bash -gh pr view --repo "$REPO" \ - --json number,title,body,labels,author,assignees,mergedAt,url - -gh issue view --repo "$REPO" \ - --json number,title,body,labels,author,assignees,url -``` - -To find issues closed by a PR via the CLI: - -```bash -# Search for closed issues linked to the PR -gh search issues --repo "$REPO" --state closed "linked:pr " -``` - -## Step 6: Categorize by Area/Theme/Impact - -Group PRs into tiers: -- **Headline features**: New namespaces or types, implementations of new industry trends/algorithms, major new API surfaces -- **Quality**: PRs or groups of PRs that improve quality across an area (recognizing `area-*` labels on the PRs and issues) -- **Performance**: PRs with benchmark data showing measurable improvements -- **API additions**: New methods/overloads on existing types -- **Small improvements**: Single-mapping additions, minor fixes with public API changes -- **Community contributions**: Large PRs labeled as `community-contribution` or collections of such PRs by the same author - -**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. +| Step | Description | Reference | +|------|-------------|-----------| +| 2.1 | **Deduplicate** — Remove features already covered in prior release notes, flag earlier PRs for review | [verify-1-dedupe.md](verify-1-dedupe.md) | +| 2.2 | **Confirm release branch** — Verify candidate changes are present in the `dotnet/dotnet` VMR release branch | [verify-2-release.md](verify-2-release.md) | -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. +## Step 3: Author Content -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. +Write the release notes document. -Some example sets of release notes to use for reference and inspiration: -* `release-notes/11.0/preview/preview1/libraries.md` -* `release-notes/10.0/preview/preview1/libraries.md` -* `release-notes/9.0/preview/rc1/libraries.md` +| Step | Description | Reference | +|------|-------------|-----------| +| 3.1 | **Categorize entries** — Group PRs by area/theme/impact into tiers; identify multi-faceted PRs | [author-1-entries.md](author-1-entries.md) | +| 3.2 | **Format** — Apply the document structure and section layout | [author-2-format.md](author-2-format.md) | +| 3.3 | **Editorial** — Apply rules for benchmarks, attribution, naming, and ranking | [author-3-editorial.md](author-3-editorial.md) | ## Cache Directory Structure From 5b96cccb92afb86fce96eb7d40029b60e85b3425 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 03:57:11 -0800 Subject: [PATCH 11/14] 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 --- .../skills/libraries-release-notes/SKILL.md | 41 +++++++++++++++---- .../references/data-1-apidiff-review.md | 4 +- .../references/data-2-collect-prs.md | 14 +++---- .../references/data-3-enrich.md | 2 + .../references/workflow.md | 39 ++++++++++++------ 5 files changed, 67 insertions(+), 33 deletions(-) diff --git a/.github/skills/libraries-release-notes/SKILL.md b/.github/skills/libraries-release-notes/SKILL.md index 8012a8938a7..444ac9a978c 100644 --- a/.github/skills/libraries-release-notes/SKILL.md +++ b/.github/skills/libraries-release-notes/SKILL.md @@ -11,15 +11,38 @@ Generate .NET Libraries release notes for a given release. ## Inputs -If `$ARGUMENTS` is provided, use `$0` as the repository. Otherwise ask the user for: -1. **Repository** — GitHub `owner/repo` to pull PRs from (e.g. `dotnet/runtime`) - -Then ask for: -2. **Preview name** (e.g. ".NET 11 Preview 1") -3. **Date range** — ask for the start and end dates separately using the .NET release calendar's "Code complete" milestones: - - **Start date**: Ask for the Code Complete date of the *previous* release. For example, when generating .NET 11 Preview 2 notes, ask: *"What is the Code Complete date for .NET 11 Preview 1? (ISO 8601, e.g. 2026-01-27)"*. When generating **Preview 1** notes, ask for the *previous major version's* RC1 Code Complete date instead (e.g. *"What is the Code Complete date for .NET 10 RC1?"*), since that is when the vNext fork occurs. Reassure the user that anything already covered in the prior version's RC1, RC2, or GA release notes will be de-duplicated in the [verify scope](references/verify-1-dedupe.md) step. - - **End date**: Ask for the Code Complete date of the *current* release. For example: *"What is the Code Complete date for .NET 11 Preview 1?"* -4. **Output file** — path for the release notes markdown (default: `release-notes/11.0/preview/preview1/libraries.md`) +If `$ARGUMENTS` is provided, use `$0` as the repository. Otherwise ask the user for the **repository** (`owner/repo`, e.g. `dotnet/runtime`). + +Collect inputs **one at a time** — ask a single question, wait for the answer, then ask the next. After each response, acknowledge what has been collected so far and ask for the next missing input: + +1. **Preview name** (e.g. ".NET 11 Preview 2") +2. **Start date** — ask: *"What was the Code Complete date for the previous release, ``?"* (ISO 8601). For **Preview 1**, this is the prior major version's RC1 Code Complete date (the vNext fork point); anything already covered in RC1/RC2/GA release notes will be de-duplicated in the [verify scope](references/verify-1-dedupe.md) step. +3. **End date** — ask: *"What was the Code Complete date for ``? (If it hasn't occurred yet, provide the expected date.)"* (ISO 8601) +4. **Output file** — path for the release notes markdown (default: `release-notes//preview//libraries.md`) + +Once all inputs are collected, **check for API diffs before proceeding** (see below), then start the data pipeline without further confirmation. + +## Early API Diff Check + +Before starting the data pipeline, verify that the required API diffs are present in the local repository clone. Check for both: + +1. **Current release API diff** — e.g. `release-notes//preview//api-diff/Microsoft.NETCore.App/` +2. **Previous release API diff** — e.g. `release-notes//preview//api-diff/Microsoft.NETCore.App/` (used during [deduplication](references/verify-1-dedupe.md) and cross-referencing) + +If **either** API diff directory is missing or empty: + +- **Warn the user immediately**, specifying which diff is missing and the expected path. +- Explain that the API diff significantly improves the quality of the release notes by enabling accurate cross-referencing of new APIs with implementing PRs. +- Ask whether to proceed without it or wait until the API diff is available. + +Do not defer this check to the data pipeline — surface the warning as soon as inputs are collected so the user can decide early whether to generate the API diff first. + +## Execution guidelines + +- **Do not write intermediate files to disk.** All data fetching (PR lists, PR details, issue details) uses GitHub MCP server tools or the `gh` CLI, and results should be processed directly in memory. Use the **SQL tool** for structured storage and querying (see [workflow.md](references/workflow.md) for schema). Disk writes trigger unnecessary approval prompts. +- **Do not use shell commands for data processing.** Filter and transform PR/issue data using the SQL tool or direct tool output — not PowerShell scripts that parse JSON files. +- **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. +- **Maximize parallel tool calls.** Fetch multiple PR and issue details in a single response to minimize round trips. ## Process diff --git a/.github/skills/libraries-release-notes/references/data-1-apidiff-review.md b/.github/skills/libraries-release-notes/references/data-1-apidiff-review.md index 783951e5ef4..fe594a59c00 100644 --- a/.github/skills/libraries-release-notes/references/data-1-apidiff-review.md +++ b/.github/skills/libraries-release-notes/references/data-1-apidiff-review.md @@ -1,5 +1,7 @@ # Step 1: Analyze API Diff +> **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. + ## Locate the API diff 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. @@ -9,8 +11,6 @@ The API diff lives under the `release-notes` folder within an `api-diff` subfold * .NET 10 GA: `release-notes/10.0/preview/ga/api-diff/Microsoft.NETCore.App/10.0-ga.md` * .NET 11 Preview 1: `release-notes/11.0/preview/preview1/api-diff/Microsoft.NETCore.App/11.0-preview1.md` -Check the `release-notes/` folder in the current repository clone for the API diff. If it is not present locally, **warn the user** that the release notes generation gains substantial context from the API diff and suggest generating release notes after the API diff is ready. The user may choose to proceed without it, but quality will be reduced. - ## Load the API diff Once the `api-diff` folder is located, load all of the API difference files under the `Microsoft.NETCore.App` subfolder: diff --git a/.github/skills/libraries-release-notes/references/data-2-collect-prs.md b/.github/skills/libraries-release-notes/references/data-2-collect-prs.md index b3f47982bbd..f82d1288c47 100644 --- a/.github/skills/libraries-release-notes/references/data-2-collect-prs.md +++ b/.github/skills/libraries-release-notes/references/data-2-collect-prs.md @@ -25,25 +25,21 @@ If the GitHub MCP server is not available, use the `gh` CLI instead. Verify avai ```bash REPO="dotnet/runtime" # Set from user input -CACHE_DIR=".cache/${REPO}" -mkdir -p "$CACHE_DIR" # First batch (newer half of range) gh pr list --repo "$REPO" --state merged \ --search "merged:2025-12-01..2026-02-01" \ - --limit 1000 --json number,title,labels,author,mergedAt,url \ - > "$CACHE_DIR/batch1.json" + --limit 1000 --json number,title,labels,author,mergedAt,url # Second batch (older half of range) gh pr list --repo "$REPO" --state merged \ --search "merged:2025-10-01..2025-12-01" \ - --limit 1000 --json number,title,labels,author,mergedAt,url \ - > "$CACHE_DIR/batch2.json" + --limit 1000 --json number,title,labels,author,mergedAt,url ``` -### Caching +### Data storage -Regardless of which method is used, cache files are stored under `.cache///` so multiple repositories can be cached side-by-side without collision. Merge batches into `$CACHE_DIR/all_merged_prs.json`. This is the authoritative cached dataset — all subsequent steps read from cache. +Store all fetched PR data using the **SQL tool** (see [workflow.md](workflow.md) for schema). 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. ## Filter to Library PRs @@ -92,4 +88,4 @@ If such issues exist, trace them to their implementing PRs and ensure those PRs **TODO:** The API diff shows new surface area for `` but the implementing PR/issue could not be found. Investigate and fill in this section. ``` -Save to `$CACHE_DIR/library_prs.json`. +Mark matching PRs as candidates in the SQL `prs` table (`is_candidate = 1`). diff --git a/.github/skills/libraries-release-notes/references/data-3-enrich.md b/.github/skills/libraries-release-notes/references/data-3-enrich.md index 4b8438ad462..081cdcc0402 100644 --- a/.github/skills/libraries-release-notes/references/data-3-enrich.md +++ b/.github/skills/libraries-release-notes/references/data-3-enrich.md @@ -114,3 +114,5 @@ To find issues closed by a PR via the CLI: # Search for closed issues linked to the PR gh search issues --repo "$REPO" --state closed "linked:pr " ``` + +Store all fetched details using the **SQL tool** (update `body` and `reactions` columns in the `prs` table; insert into the `issues` table). Do **not** write intermediate files to disk. diff --git a/.github/skills/libraries-release-notes/references/workflow.md b/.github/skills/libraries-release-notes/references/workflow.md index 65c615a6b23..d5b51c2bb23 100644 --- a/.github/skills/libraries-release-notes/references/workflow.md +++ b/.github/skills/libraries-release-notes/references/workflow.md @@ -33,19 +33,32 @@ Write the release notes document. | 3.2 | **Format** — Apply the document structure and section layout | [author-2-format.md](author-2-format.md) | | 3.3 | **Editorial** — Apply rules for benchmarks, attribution, naming, and ranking | [author-3-editorial.md](author-3-editorial.md) | -## Cache Directory Structure +## Data Storage -``` -.cache/ -└── / - └── / - ├── all_merged_prs.json # Raw merged PR list - ├── batch1.json # First date range batch - ├── batch2.json # Second date range batch - ├── library_prs.json # Filtered to library-area PRs - ├── pr_details.json # Full PR bodies keyed by number - ├── issue_details.json # Full issue bodies keyed by number - └── coauthors.txt # Copilot PR → assignee mapping +Keep all intermediate data **in memory** — do not write cache files to disk. Use the **SQL tool** to store and query PR and issue data across steps: + +```sql +CREATE TABLE prs ( + number INTEGER PRIMARY KEY, + title TEXT, + author TEXT, + author_association TEXT, + labels TEXT, -- comma-separated label names + merged_at TEXT, + body TEXT, + reactions INTEGER DEFAULT 0, + is_library INTEGER DEFAULT 0, + is_candidate INTEGER DEFAULT 0 +); + +CREATE TABLE issues ( + number INTEGER PRIMARY KEY, + title TEXT, + body TEXT, + labels TEXT, + reactions INTEGER DEFAULT 0, + pr_number INTEGER -- the PR that references this issue +); ``` -Always check if cache files exist before re-fetching. Only re-fetch if the user asks to refresh or the date range changes. +This avoids shell commands for file I/O, which trigger unnecessary approval prompts. All filtering, dedup, and enrichment queries can run directly against these tables. From 34f37e59805f4bf35477ebb7cb87a26016ceaa9d Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 04:19:28 -0800 Subject: [PATCH 12/14] 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. --- .../skills/libraries-release-notes/SKILL.md | 6 ++- .../references/data-2-collect-prs.md | 44 ++++++++++++++----- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/.github/skills/libraries-release-notes/SKILL.md b/.github/skills/libraries-release-notes/SKILL.md index 444ac9a978c..76ea9c77118 100644 --- a/.github/skills/libraries-release-notes/SKILL.md +++ b/.github/skills/libraries-release-notes/SKILL.md @@ -39,7 +39,11 @@ Do not defer this check to the data pipeline — surface the warning as soon as ## Execution guidelines -- **Do not write intermediate files to disk.** All data fetching (PR lists, PR details, issue details) uses GitHub MCP server tools or the `gh` CLI, and results should be processed directly in memory. Use the **SQL tool** for structured storage and querying (see [workflow.md](references/workflow.md) for schema). Disk writes trigger unnecessary approval prompts. +- **Avoid large MCP responses.** 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: + - Use **label-scoped searches** (e.g. `label:area-System.Text.Json`) instead of fetching all merged PRs at once. See [data-2-collect-prs.md](references/data-2-collect-prs.md) for the recommended approach. + - Use `perPage: 30` or less for search queries. Only use `perPage: 100` for targeted queries that are expected to return few results. + - 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. +- **Do not write intermediate files to disk.** Use the **SQL tool** for structured storage and querying (see [workflow.md](references/workflow.md) for schema). - **Do not use shell commands for data processing.** Filter and transform PR/issue data using the SQL tool or direct tool output — not PowerShell scripts that parse JSON files. - **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. - **Maximize parallel tool calls.** Fetch multiple PR and issue details in a single response to minimize round trips. diff --git a/.github/skills/libraries-release-notes/references/data-2-collect-prs.md b/.github/skills/libraries-release-notes/references/data-2-collect-prs.md index f82d1288c47..7e57d709856 100644 --- a/.github/skills/libraries-release-notes/references/data-2-collect-prs.md +++ b/.github/skills/libraries-release-notes/references/data-2-collect-prs.md @@ -2,22 +2,48 @@ ## Fetch Merged PRs -Pull all merged PRs in the date range from the specified repository. The primary method is the **GitHub MCP server** tools; fall back to the **GitHub CLI (`gh`)** if the MCP server is unavailable. +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. ### Primary — GitHub MCP server -Use `search_pull_requests` to query for merged PRs. The initial query should fetch **all** merged PRs in the date range without label filtering, to avoid missing PRs labeled with less-common area labels (e.g. `area-System.DateTime`, `area-System.Reflection.Emit`, `area-System.Globalization`). Split the date range into sub-ranges if needed to stay within GitHub's 1,000-result search limit. +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). + +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: + +``` +# Search per area label — one query per label, small result sets +search_pull_requests( + owner: "dotnet", + repo: "runtime", + query: "is:merged merged:2026-01-26..2026-02-11 label:area-System.Text.Json", + perPage: 30 +) +``` + +**Recommended area labels to search** (run these in parallel batches): + +- `area-System.Text.Json`, `area-System.Net.Http`, `area-System.Collections` +- `area-System.IO`, `area-System.IO.Compression`, `area-System.Threading` +- `area-System.Numerics`, `area-System.Runtime`, `area-System.Memory` +- `area-System.Security`, `area-System.Diagnostics`, `area-System.Globalization` +- `area-System.Linq`, `area-System.Reflection`, `area-System.Reflection.Emit` +- `area-System.Formats.*`, `area-System.Net.*`, `area-System.Text.*` +- `area-Microsoft.Extensions.*`, `area-Extensions-*` + +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: ``` search_pull_requests( owner: "dotnet", repo: "runtime", - query: "is:merged merged:2025-12-01..2026-02-01", - perPage: 100 + query: "is:merged merged:2026-01-26..2026-02-11 label:area-System", + perPage: 30 ) ``` -Page through results (incrementing `page`) until all PRs are collected. If a single date range returns close to 1,000 results, split into smaller sub-ranges (e.g. halve the range) and repeat. Do **not** restrict the initial search to specific area labels — label-based filtering happens later in the filtering step. +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. + +**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. ### Fallback — GitHub CLI @@ -43,13 +69,9 @@ Store all fetched PR data using the **SQL tool** (see [workflow.md](workflow.md) ## Filter to Library PRs -### Label-based filtering - -From the merged set, keep only PRs that have a label matching any `area-System.*`, `area-Microsoft.Extensions*`, or `area-Extensions-*` pattern. Match the label prefix broadly — do **not** use a hard-coded list of specific area labels, as that risks missing PRs labeled with less-common areas (e.g. `area-System.DateTime`, `area-System.Reflection.Emit`, `area-System.Globalization`). - -**PRs without area labels.** PR labels cannot be entirely trusted — some PRs lack an `area-*` label altogether. Do not discard these PRs immediately. Instead, check their linked or related issues (from the PR description's "Fixes #..." references) for `area-*` labels. If a related issue carries a matching `area-System.*`, `area-Microsoft.Extensions*`, or `area-Extensions-*` label, include the PR in the candidate list. +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: -Additionally exclude: +### Exclusion filters - Labels: `backport`, `servicing`, `NO-MERGE` - PRs whose title starts with `[release/` or contains `backport` - PRs that are purely test, CI, or documentation changes (no `src` changes) From baf96804b52c415262481c050992629cfd4e8013 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 04:59:37 -0800 Subject: [PATCH 13/14] Undo .gitignore cache addition for the libraries-release-notes skill --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 04fa0dc412e..5bbb800fddc 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,3 @@ msbuild.wrn node_modules/ package-lock.json package.json - -# Release notes generator cache -.cache/ From bd37d8c21a253877e59ccb9565558519dc6a04c9 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 10 Feb 2026 05:24:20 -0800 Subject: [PATCH 14/14] Refactor SKILL.md: extract inputs to reference file, relocate guidelines, remove workflow.md --- .../skills/libraries-release-notes/SKILL.md | 44 ++----------- .../references/data-2-collect-prs.md | 36 ++++++++++- .../references/data-3-enrich.md | 8 +++ .../references/process-inputs.md | 29 +++++++++ .../references/workflow.md | 64 ------------------- 5 files changed, 78 insertions(+), 103 deletions(-) create mode 100644 .github/skills/libraries-release-notes/references/process-inputs.md delete mode 100644 .github/skills/libraries-release-notes/references/workflow.md diff --git a/.github/skills/libraries-release-notes/SKILL.md b/.github/skills/libraries-release-notes/SKILL.md index 76ea9c77118..94f76ca3852 100644 --- a/.github/skills/libraries-release-notes/SKILL.md +++ b/.github/skills/libraries-release-notes/SKILL.md @@ -9,56 +9,24 @@ argument-hint: "[owner/repo]" Generate .NET Libraries release notes for a given release. -## Inputs - -If `$ARGUMENTS` is provided, use `$0` as the repository. Otherwise ask the user for the **repository** (`owner/repo`, e.g. `dotnet/runtime`). - -Collect inputs **one at a time** — ask a single question, wait for the answer, then ask the next. After each response, acknowledge what has been collected so far and ask for the next missing input: - -1. **Preview name** (e.g. ".NET 11 Preview 2") -2. **Start date** — ask: *"What was the Code Complete date for the previous release, ``?"* (ISO 8601). For **Preview 1**, this is the prior major version's RC1 Code Complete date (the vNext fork point); anything already covered in RC1/RC2/GA release notes will be de-duplicated in the [verify scope](references/verify-1-dedupe.md) step. -3. **End date** — ask: *"What was the Code Complete date for ``? (If it hasn't occurred yet, provide the expected date.)"* (ISO 8601) -4. **Output file** — path for the release notes markdown (default: `release-notes//preview//libraries.md`) - -Once all inputs are collected, **check for API diffs before proceeding** (see below), then start the data pipeline without further confirmation. - -## Early API Diff Check - -Before starting the data pipeline, verify that the required API diffs are present in the local repository clone. Check for both: - -1. **Current release API diff** — e.g. `release-notes//preview//api-diff/Microsoft.NETCore.App/` -2. **Previous release API diff** — e.g. `release-notes//preview//api-diff/Microsoft.NETCore.App/` (used during [deduplication](references/verify-1-dedupe.md) and cross-referencing) - -If **either** API diff directory is missing or empty: - -- **Warn the user immediately**, specifying which diff is missing and the expected path. -- Explain that the API diff significantly improves the quality of the release notes by enabling accurate cross-referencing of new APIs with implementing PRs. -- Ask whether to proceed without it or wait until the API diff is available. - -Do not defer this check to the data pipeline — surface the warning as soon as inputs are collected so the user can decide early whether to generate the API diff first. - ## Execution guidelines -- **Avoid large MCP responses.** 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: - - Use **label-scoped searches** (e.g. `label:area-System.Text.Json`) instead of fetching all merged PRs at once. See [data-2-collect-prs.md](references/data-2-collect-prs.md) for the recommended approach. - - Use `perPage: 30` or less for search queries. Only use `perPage: 100` for targeted queries that are expected to return few results. - - 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. -- **Do not write intermediate files to disk.** Use the **SQL tool** for structured storage and querying (see [workflow.md](references/workflow.md) for schema). -- **Do not use shell commands for data processing.** Filter and transform PR/issue data using the SQL tool or direct tool output — not PowerShell scripts that parse JSON files. +- **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). - **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. - **Maximize parallel tool calls.** Fetch multiple PR and issue details in a single response to minimize round trips. ## Process -1. **[Data pipeline](references/workflow.md)** — gather the changes included in the release: +1. **[Process Inputs and Validate Readiness](references/process-inputs.md)** — collect inputs and verify API diffs are available. +2. **Data pipeline** — gather the changes included in the release: 1. [Analyze the API diff](references/data-1-apidiff-review.md) 2. [Collect and filter PRs](references/data-2-collect-prs.md) 3. [Enrich — fetch PR and issue details](references/data-3-enrich.md) -2. **Verify scope** — validate the candidate list: +3. **Verify scope** — validate the candidate list: 1. [Deduplicate from previous release notes](references/verify-1-dedupe.md) 2. [Confirm inclusion in release branch](references/verify-2-release.md) -3. **Author content** — write the release notes: +4. **Author content** — write the release notes: 1. [Categorize entries by area, theme, and impact](references/author-1-entries.md) 2. [Apply formatting rules](references/author-2-format.md) 3. [Apply editorial rules](references/author-3-editorial.md) -4. Confirm feature list with the user before finalizing. +5. Confirm feature list with the user before finalizing. diff --git a/.github/skills/libraries-release-notes/references/data-2-collect-prs.md b/.github/skills/libraries-release-notes/references/data-2-collect-prs.md index 7e57d709856..9cb21d6fa7e 100644 --- a/.github/skills/libraries-release-notes/references/data-2-collect-prs.md +++ b/.github/skills/libraries-release-notes/references/data-2-collect-prs.md @@ -1,5 +1,13 @@ # Step 2: Collect and Filter PRs +## MCP response size + +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: + +- Use **label-scoped searches** (e.g. `label:area-System.Text.Json`) instead of fetching all merged PRs at once. +- Use `perPage: 30` or less for search queries. Only use `perPage: 100` for targeted queries that are expected to return few results. +- 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. + ## Fetch Merged PRs 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. @@ -65,7 +73,33 @@ gh pr list --repo "$REPO" --state merged \ ### Data storage -Store all fetched PR data using the **SQL tool** (see [workflow.md](workflow.md) for schema). 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. +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. + +```sql +CREATE TABLE prs ( + number INTEGER PRIMARY KEY, + title TEXT, + author TEXT, + author_association TEXT, + labels TEXT, -- comma-separated label names + merged_at TEXT, + body TEXT, + reactions INTEGER DEFAULT 0, + is_library INTEGER DEFAULT 0, + is_candidate INTEGER DEFAULT 0 +); + +CREATE TABLE issues ( + number INTEGER PRIMARY KEY, + title TEXT, + body TEXT, + labels TEXT, + reactions INTEGER DEFAULT 0, + pr_number INTEGER -- the PR that references this issue +); +``` + +Additional PRs can be added to the candidate list manually by number. Use [Enrich](data-3-enrich.md) to fetch their details. ## Filter to Library PRs diff --git a/.github/skills/libraries-release-notes/references/data-3-enrich.md b/.github/skills/libraries-release-notes/references/data-3-enrich.md index 081cdcc0402..17caeee4e19 100644 --- a/.github/skills/libraries-release-notes/references/data-3-enrich.md +++ b/.github/skills/libraries-release-notes/references/data-3-enrich.md @@ -2,6 +2,14 @@ For each library PR, fetch the full body (description) which contains benchmark data, API signatures, and motivation. Building on the PR data, fetch the details for issues referenced by or linked to the pull request — especially any issues resolved by the PR. Issues labeled `api-approved` represent new APIs being added and should be represented in the API diff if it was loaded. The issue often has a more detailed description than the PR, including API usage examples and a statement of impact/value. The final API shape (and usage example) might be somewhat out of date compared to what was approved and merged in the pull request, so usage examples may need to be revised. +## MCP response size + +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: + +- Use **label-scoped searches** (e.g. `label:area-System.Text.Json`) instead of fetching all merged PRs at once. +- Use `perPage: 30` or less for search queries. Only use `perPage: 100` for targeted queries that are expected to return few results. +- 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. + ## Fetch PR details — GitHub MCP server (primary) Use `pull_request_read` with method `get` to fetch each PR's full details: diff --git a/.github/skills/libraries-release-notes/references/process-inputs.md b/.github/skills/libraries-release-notes/references/process-inputs.md new file mode 100644 index 00000000000..9ef520200e6 --- /dev/null +++ b/.github/skills/libraries-release-notes/references/process-inputs.md @@ -0,0 +1,29 @@ +# Process Inputs and Validate Readiness + +Collect all required inputs from the user and verify that prerequisite data is available before starting the data pipeline. + +## Inputs + +If `$ARGUMENTS` is provided, use `$0` as the repository. Otherwise ask the user for the **repository** (`owner/repo`, e.g. `dotnet/runtime`). + +Collect inputs **one at a time** — ask a single question, wait for the answer, then ask the next. After each response, acknowledge what has been collected so far and ask for the next missing input: + +1. **Preview name** (e.g. ".NET 11 Preview 2") +2. **Start date** — ask: *"What was the Code Complete date for the previous release, ``?"* (ISO 8601). For **Preview 1**, this is the prior major version's RC1 Code Complete date (the vNext fork point); anything already covered in RC1/RC2/GA release notes will be de-duplicated in the [verify scope](verify-1-dedupe.md) step. +3. **End date** — ask: *"What was the Code Complete date for ``? (If it hasn't occurred yet, provide the expected date.)"* (ISO 8601) +4. **Output file** — path for the release notes markdown (default: `release-notes//preview//libraries.md`) + +## Early API Diff Check + +Before starting the data pipeline, verify that the required API diffs are present in the local repository clone. Check for both: + +1. **Current release API diff** — e.g. `release-notes//preview//api-diff/Microsoft.NETCore.App/` +2. **Previous release API diff** — e.g. `release-notes//preview//api-diff/Microsoft.NETCore.App/` (used during [deduplication](verify-1-dedupe.md) and cross-referencing) + +If **either** API diff directory is missing or empty: + +- **Warn the user immediately**, specifying which diff is missing and the expected path. +- Explain that the API diff significantly improves the quality of the release notes by enabling accurate cross-referencing of new APIs with implementing PRs. +- Ask whether to proceed without it or wait until the API diff is available. + +Do not defer this check to the data pipeline — surface the warning as soon as inputs are collected so the user can decide early whether to generate the API diff first. diff --git a/.github/skills/libraries-release-notes/references/workflow.md b/.github/skills/libraries-release-notes/references/workflow.md deleted file mode 100644 index d5b51c2bb23..00000000000 --- a/.github/skills/libraries-release-notes/references/workflow.md +++ /dev/null @@ -1,64 +0,0 @@ -# Data Pipeline — Gathering the changes included in the release - -This workflow orchestrates the full process for generating .NET Libraries release notes. Each step is documented in its own reference file and can be invoked independently. - -## Step 1: Data Pipeline - -Gather and enrich the candidate changes for the release. - -| Step | Description | Reference | -|------|-------------|-----------| -| 1.1 | **Analyze API Diff** — Locate and load the API diff to understand new/changed APIs | [data-1-apidiff-review.md](data-1-apidiff-review.md) | -| 1.2 | **Collect & Filter PRs** — Fetch merged PRs, filter to library areas, cross-reference API diff | [data-2-collect-prs.md](data-2-collect-prs.md) | -| 1.3 | **Enrich** — Fetch full PR details, Copilot summaries, backing issues, and reaction counts | [data-3-enrich.md](data-3-enrich.md) | - -After Step 1.2, additional PRs can be added to the candidate list manually by number. Use Step 1.3 to fetch their details. - -## Step 2: Verify Scope - -Validate the candidate list before authoring content. These verification steps apply to all candidates, including any manually added PRs. - -| Step | Description | Reference | -|------|-------------|-----------| -| 2.1 | **Deduplicate** — Remove features already covered in prior release notes, flag earlier PRs for review | [verify-1-dedupe.md](verify-1-dedupe.md) | -| 2.2 | **Confirm release branch** — Verify candidate changes are present in the `dotnet/dotnet` VMR release branch | [verify-2-release.md](verify-2-release.md) | - -## Step 3: Author Content - -Write the release notes document. - -| Step | Description | Reference | -|------|-------------|-----------| -| 3.1 | **Categorize entries** — Group PRs by area/theme/impact into tiers; identify multi-faceted PRs | [author-1-entries.md](author-1-entries.md) | -| 3.2 | **Format** — Apply the document structure and section layout | [author-2-format.md](author-2-format.md) | -| 3.3 | **Editorial** — Apply rules for benchmarks, attribution, naming, and ranking | [author-3-editorial.md](author-3-editorial.md) | - -## Data Storage - -Keep all intermediate data **in memory** — do not write cache files to disk. Use the **SQL tool** to store and query PR and issue data across steps: - -```sql -CREATE TABLE prs ( - number INTEGER PRIMARY KEY, - title TEXT, - author TEXT, - author_association TEXT, - labels TEXT, -- comma-separated label names - merged_at TEXT, - body TEXT, - reactions INTEGER DEFAULT 0, - is_library INTEGER DEFAULT 0, - is_candidate INTEGER DEFAULT 0 -); - -CREATE TABLE issues ( - number INTEGER PRIMARY KEY, - title TEXT, - body TEXT, - labels TEXT, - reactions INTEGER DEFAULT 0, - pr_number INTEGER -- the PR that references this issue -); -``` - -This avoids shell commands for file I/O, which trigger unnecessary approval prompts. All filtering, dedup, and enrichment queries can run directly against these tables.