diff --git a/.github/skills/api-diff-validation/SKILL.md b/.github/skills/api-diff-validation/SKILL.md index 6cc13f6e6c5..771c9d54fe4 100644 --- a/.github/skills/api-diff-validation/SKILL.md +++ b/.github/skills/api-diff-validation/SKILL.md @@ -38,8 +38,8 @@ the real ref packs from the build's feed, so it answers "does this API exist in Read `build-metadata.json` for the target. Use its `nuget.source` as `$FEED` and the ref-pack versions (e.g. `Microsoft.NETCore.App.Ref@`) as `$VER`. For behavior that requires the SDK (rare here), install it side-by-side and scoped — -see the `validate-code-samples` skill. Do **not** trust a machine-wide SDK for -preview work. +see the [`validate-code-samples`](../validate-code-samples/SKILL.md) skill. Do +**not** trust a machine-wide SDK for preview work. ## 2. Verify APIs exist with dotnet-inspect diff --git a/.github/skills/generate-changes/SKILL.md b/.github/skills/generate-changes/SKILL.md index da068bceebb..7c1def69d30 100644 --- a/.github/skills/generate-changes/SKILL.md +++ b/.github/skills/generate-changes/SKILL.md @@ -126,4 +126,44 @@ The output file must follow the shared schema documented in [changes-schema.md]( - stable `id` values in `repo@shortcommit` format - same authoritative source of truth used by later skills +## Milestone cross-check + +`changes.json` is derived from a VMR source-manifest diff. That makes it authoritative for *what +flowed into the build*, but it is a commit-shaped view, and a feature can be easy to overlook in it. +For the repos that maintain preview milestones, sweep the milestone as a **second, independent view** +of the same release and reconcile anything that looks like a user-facing feature but never made it +into the notes. + +```bash +gh api -X GET search/issues \ + -f q="repo:dotnet/aspnetcore is:pr is:merged milestone:11.0-preview7" \ + --jq '.total_count' +``` + +Milestone discipline varies by repo, so this check only applies for the repos where it is actually maintained: + +- dotnet/sdk +- dotnet/aspnetcore +- dotnet/runtime +- dotnet/efcore + +Rules for using it: + +- **Supplement, never replace.** `changes.json` stays the source of truth. The milestone is a + prompt to go back and look, not an alternative manifest. +- **The milestone is a subset.** It excludes infrastructure and dependency-flow PRs that + legitimately appear in `changes.json`, so the counts will not match and are not meant to. +- **Only the missing direction matters.** What is worth acting on is a PR in the milestone that + describes a user-facing change and has no corresponding entry in the notes. +- **Verify every addition independently before writing it up.** Milestones are applied by + automation, so they are usually right — but they can be changed or applied incorrectly by hand + afterwards, and a milestoned PR can still be reverted. Treat a milestone as reliable evidence of + where to look and strong but not conclusive evidence that the change shipped. Before promoting + anything found this way, confirm it appears in `changes.json` and exists in the build (see + [`api-verification.md`](../release-notes/references/api-verification.md) and + [`validate-code-samples`](../validate-code-samples/SKILL.md)). The expected outcome is that it + checks out; the point is to catch the occasional one that does not. +- **Confirm the milestone exists before relying on its absence.** Repos without `11.x` milestones + will return zero results, which means "not tracked here", not "nothing shipped". + Once `changes.json` exists, the next step is usually `generate-features`. diff --git a/.github/skills/release-notes/SKILL.md b/.github/skills/release-notes/SKILL.md index 15368922ea3..ada31355ea7 100644 --- a/.github/skills/release-notes/SKILL.md +++ b/.github/skills/release-notes/SKILL.md @@ -1,7 +1,7 @@ --- name: release-notes -description: Generate and maintain .NET release notes from `features.json`. Uses `generate-changes` for authoritative shipped-change data, `generate-features` for scoring/triage, `update-existing-branch` for incremental reruns on populated branches, `editorial-scoring` for the shared rubric, `api-diff` to generate API diff reports and `api-diff-validation` for API verification, and a multi-model `review-release-notes` pass for final editorial QA. -compatibility: Requires GitHub MCP server or gh CLI for cross-repo queries. Pairs with the generate-changes, generate-features, update-existing-branch, editorial-scoring, api-diff, api-diff-validation, and review-release-notes skills. Claude Opus 4.6 is the default workflow model; the preferred final reviewer pair is Claude Opus 4.6 + GPT-5.4 for broader editorial feedback. +description: Generate and maintain .NET release notes from `features.json`. Uses `generate-changes` for authoritative shipped-change data, `generate-features` for scoring/triage, `update-existing-branch` for incremental reruns on populated branches, `editorial-scoring` for the shared rubric, `api-diff` to generate API diff reports, `api-diff-validation` for API verification, `validate-code-samples` to build and run the documented claims against the milestone build, and a multi-model `review-release-notes` pass for final editorial QA. +compatibility: Requires GitHub MCP server or gh CLI for cross-repo queries. Pairs with the generate-changes, generate-features, update-existing-branch, editorial-scoring, api-diff, api-diff-validation, validate-code-samples, and review-release-notes skills. Claude Opus 4.6 is the default workflow model; the preferred final reviewer pair is Claude Opus 4.6 + GPT-5.4 for broader editorial feedback. --- # .NET Release Notes @@ -17,8 +17,9 @@ This skill is the **editorial writing stage** of the pipeline. It turns a scored 3. `update-existing-branch` handles incremental reruns when a milestone branch already exists, merging deltas instead of restarting from scratch 4. `api-diff-validation` / `dotnet-inspect` verifies public APIs and confirms suspect features still exist in the shipped build 5. `release-notes` writes curated markdown using the higher-value entries from `features.json` -6. `review-release-notes` runs a final multi-model editorial QA pass against the scoring rubric and examples -7. Output is a set of pull requests per release milestone in dotnet/core: a base PR that holds shared metadata (`changes.json`, `features.json`, `README.md`, `build-metadata.json`) and one PR per component file. Each component PR targets the base branch so component teams review and edit their file in isolation. See [`pr-layout.md`](references/pr-layout.md) for the full layout and naming scheme. +6. `validate-code-samples` builds and runs the documented claims against the milestone build, catching what static API verification cannot see +7. `review-release-notes` runs a final multi-model editorial QA pass against the scoring rubric and examples +8. Output is a set of pull requests per release milestone in dotnet/core: a base PR that holds shared metadata (`changes.json`, `features.json`, `README.md`, `build-metadata.json`) and one PR per component file. Each component PR targets the base branch so component teams review and edit their file in isolation. See [`pr-layout.md`](references/pr-layout.md) for the full layout and naming scheme. ## Local testing (no PRs) @@ -45,4 +46,5 @@ handling review comments without clobbering human edits. - [format-template.md](references/format-template.md) — markdown document structure - [editorial-rules.md](references/editorial-rules.md) — tone, attribution, naming - [api-verification.md](references/api-verification.md) — using dotnet-inspect to verify APIs +- [../validate-code-samples/SKILL.md](../validate-code-samples/SKILL.md) — building and running the documented claims against the milestone build - [examples/](references/examples/) — curated examples from previous releases, organized by component. **Read the examples for your component before writing.** The [examples/README.md](references/examples/README.md) lists 12 editorial principles derived from what works and what doesn't in past release notes. diff --git a/.github/skills/release-notes/references/api-verification.md b/.github/skills/release-notes/references/api-verification.md index 3aee81934f1..03d3dc872c3 100644 --- a/.github/skills/release-notes/references/api-verification.md +++ b/.github/skills/release-notes/references/api-verification.md @@ -116,6 +116,32 @@ You do NOT need to verify: - General concepts (e.g., "Zstandard compression" as a concept vs `ZstandardCompressionProvider` as a type) - CLI flags (e.g., `dotnet test --artifacts-path`) +## Verify the change shipped in *this* milestone + +API verification answers "does this exist in the build". It does not answer "did this change in this +release" — and those come apart in a way that is easy to miss. + +A behavior observed in the Preview 7 build was traced to a fix that shipped in **Preview 3**. It was +real, it was verifiable, and documenting it in the Preview 7 notes would have been wrong. Anything +still present from an earlier release will verify perfectly against the current build. + +The rule: **every documented change must trace to a PR associated with this milestone**, not merely be observably +true in the build. + +1. **`changes.json` membership is the primary test.** If a change has no entry, it did not flow into + this milestone. Confirm before writing it up. +2. **Check the PR's merge date and milestone** where the repo maintains them — + `dotnet/aspnetcore`, `dotnet/runtime`, `dotnet/sdk`, and `dotnet/efcore` do; + `dotnet/roslyn` and `dotnet/razor` do not (see + [`generate-changes`](../../generate-changes/SKILL.md)). For repos without milestones, + `changes.json` membership is the only available provenance signal. +3. **Be suspicious of anything discovered by testing rather than from `changes.json`.** Finding a + nice behavior while validating samples is a good way to find *previous* releases' features. Trace + it to a PR associated with this milestone before promoting it. + +This is the mirror image of the revert check below: a revert means something in `changes.json` is not +in the build, and stale provenance means something in the build is not in `changes.json`. + ## What to do when verification fails If `dotnet-inspect` can't find a type: @@ -128,4 +154,16 @@ If `dotnet-inspect` can't find a type: When in doubt, describe the feature without naming specific types and link to the PR. A correct prose description is always better than a wrong code sample. +## Static verification is not enough + +Everything above confirms that a *managed symbol exists*. Three important classes of error survive it: + +- **JavaScript and browser-facing APIs** are invisible to `dotnet-inspect` entirely. +- **Defaults and polarity** are not checked by a name lookup. A rename from `EnableX` to `DisableX` + passes an existence check while inverting the meaning of the documented claim. +- **Runtime behavior** — a sample can compile and still fail on request. + +After the notes are drafted, run [`validate-code-samples`](../../validate-code-samples/SKILL.md) to +build and execute the documented claims against the milestone build. + For scoring and feature selection, this is also a **quality bar**: if a change only looks interesting because it seems to add a new API, but you cannot identify that API in the public surface, score it down sharply. That usually means it is internal plumbing, a refactor, or an existing niche surface getting maintenance rather than a real release-note feature. diff --git a/.github/skills/release-notes/references/component-mapping.md b/.github/skills/release-notes/references/component-mapping.md index 37d7ae8c79e..b6319b0ab1e 100644 --- a/.github/skills/release-notes/references/component-mapping.md +++ b/.github/skills/release-notes/references/component-mapping.md @@ -24,6 +24,19 @@ Each release notes file gets its own per-component branch named `release-notes/{ The agent assigns each component PR to its default assignee(s) when opening the PR (`gh pr create --assignee ...`), so the right team sees it in their review queue. +### Check that the owners are still current + +This table is maintained by hand and goes stale as people change roles. Before opening the PRs, confirm each assignee can actually be assigned: + +```bash +gh api repos/dotnet/core/assignees/ --silent # exit 0 = assignable, 404 = not +``` + +A 404 means the mapping is stale, not that the call failed — GitHub will accept the PR creation and +silently drop that assignee. Treat it as a prompt to confirm the current owner and update this file, +rather than working around it. See [`pr-layout.md`](pr-layout.md) for the verification step after +the PRs are created. + ### Components contributed out-of-band (not in the VMR) These components ship with .NET but live outside the VMR, so `changes.json` won't contain entries for them. The agent still creates a stub PR for each so the component team can push their own content (or close the PR if there is nothing noteworthy this milestone). diff --git a/.github/skills/release-notes/references/editorial-rules.md b/.github/skills/release-notes/references/editorial-rules.md index d4cf65d3c2e..89a0f28c7b7 100644 --- a/.github/skills/release-notes/references/editorial-rules.md +++ b/.github/skills/release-notes/references/editorial-rules.md @@ -108,18 +108,36 @@ Thank you contributors! ❤️ ## Bug fixes section -After features but before community contributors, include a grouped bug fix summary when there are noteworthy fixes. When citing the source work, use linked `org/repo #number` references with a space before `#`: +After features but before community contributors, include a bug fix summary when there are noteworthy fixes. + +Group the fixes by namespace or area, with a **flat list of one bullet per fix** under each group. Each bullet is a single markdown link whose target is the PR that made the fix and whose display text is a cleaned-up version of the PR or issue title: ```markdown ## Bug fixes - **System.Net.Http** - - Fixed authenticated proxy credential handling ([dotnet/runtime #123363](https://github.com/dotnet/runtime/issues/123363)) + - [Fix authenticated proxy credential handling](https://github.com/dotnet/runtime/pull/123363) - **System.Collections** - - Fixed integer overflow in ImmutableArray range validation ([dotnet/runtime #124042](https://github.com/dotnet/runtime/pull/124042)) + - [Fix integer overflow in ImmutableArray range validation](https://github.com/dotnet/runtime/pull/124042) ``` -Group by namespace/area. Don't include test-only, CI, or infra fixes. +Rules: + +- **One fix per bullet.** If a single behavior was fixed by several PRs, give each PR its own bullet rather than bundling links into one sentence. +- **Link to the PR**, not the issue, even when the issue has the better title. Take the wording from whichever reads more clearly and point the link at the PR. +- **Group by namespace or area**, exactly one level deep. Use the namespace where the component has one (`System.Text.Json`), otherwise a feature area (`Blazor`, `JIT / code generation`). +- **No trailing prose.** The bullet is the link and nothing else — no explanation after it, and no `org/repo #number` citation, since the link already carries that. + +This overrides the general `org/repo #number` citation style used elsewhere in the notes; that style still applies in feature sections and breaking changes. + +Cleaning up the title means making it read as a plain description of the fix: + +- Drop branch and process prefixes (`[release/11.0]`, `[main]`, backport markers). +- Drop trailing issue references (`(#12345)`, `Fixes #123`). +- Expand cryptic shorthand into words a reader outside the team would recognize. +- Keep it a single line. If the title is unintelligible without context, rewrite it as a short description of the fix rather than pasting the raw title. + +Don't include test-only, CI, or infra fixes. ## Preview-to-preview feedback fixes diff --git a/.github/skills/release-notes/references/format-template.md b/.github/skills/release-notes/references/format-template.md index 0e8618e6c62..8a9d58ddeb0 100644 --- a/.github/skills/release-notes/references/format-template.md +++ b/.github/skills/release-notes/references/format-template.md @@ -24,7 +24,8 @@ Standard document structure for .NET release notes markdown files. ## Bug fixes -- **Category** — Fix description +- **Namespace or area** + - [Cleaned up PR or issue title](https://github.com///pull/NNNNN) ## Community contributors @@ -87,9 +88,42 @@ Known component docs links: 2. **One paragraph of context** — what the feature does and why it matters in concrete terms, with PR/issue links; avoid inferred feelings or marketing-style claims 3. **Code sample** — show the feature in use 4. **Feature ordering** — highest customer impact first -5. **Breaking changes near the end** — low-score entries with `breaking_changes: true` usually belong in a short section before Bug fixes, not as full feature sections +5. **Breaking changes near the end** — low-score entries with `breaking_changes: true` usually belong in a short section before Bug fixes, not as full feature sections. In preview notes this section is also the upgrade guidance for readers coming from the previous preview — see below 6. **Preview feature callout** — when a feature is listed in `release-notes/features.json`, start its section with the standard blockquote callout from that file +## Breaking changes + +Preview notes are read mostly by people who are already running the *previous* preview. For them the +most valuable content is often not the new feature, but the thing that stops their existing code +from building or working after they move to this build. + +Because each preview's Breaking changes section covers what changed *in that milestone*, it is +already the preview-to-preview upgrade story. Write it for the reader doing that upgrade rather than +as an abstract list of incompatibilities with the last GA release. + +Cover these when they apply. They tend to surface only when an existing project is actually upgraded +to the new build, which is one of the reasons +[`validate-code-samples`](../../validate-code-samples/SKILL.md) runs against a maintained sample set: + +- **Renamed APIs**, especially renames that invert meaning (`EnableX` becoming `DisableX`). Show the + before and after, and state the new default explicitly. +- **New analyzer diagnostics that fire on previously clean code.** Code that built without warnings + on the last preview and now reports diagnostics is an upgrade issue even though nothing in the + user's code changed. Name the diagnostic IDs. +- **Changed defaults**, where existing code keeps compiling but behaves differently. + +**Removed or replaced workarounds** are the one upgrade item that is not a breaking change. If a bug +that required a workaround is now fixed, say so with the fix in Bug fixes, so users can delete the +workaround rather than carrying it forward. + +Do not turn this into a changelog of everything that moved. Include an item only when a user +upgrading from the previous preview would otherwise hit a build error, a new warning, or a silent +behavior change. + +Attribute these to the milestone that actually changed them. A fix that shipped two previews ago is +not upgrade guidance for this one — see +[api-verification.md](api-verification.md) for the provenance rule. + ## Issue and PR references Always use markdown links with the `{org}/{repo} #{number}` format, with a space before `#`: diff --git a/.github/skills/release-notes/references/pr-layout.md b/.github/skills/release-notes/references/pr-layout.md index 23efdd4f6f3..23b4f611a7c 100644 --- a/.github/skills/release-notes/references/pr-layout.md +++ b/.github/skills/release-notes/references/pr-layout.md @@ -15,10 +15,43 @@ The set of components and their release notes files is defined in [`component-ma - Each `{component}.md` lives on its **matching component branch only**. The agent never edits another component's file from the wrong branch. - The milestone landing page `{version}.md` (for example, `11.0.0-preview.4.md`) is **not produced by this skill**. The .NET release team generates it through separate artifacts-publishing automation, so the agent leaves it alone on every branch. +## Creating the PRs + +Order matters, and two of these steps fail silently. + +1. **Push the base branch first.** Component PRs target it, so it must exist on the remote before + any component PR can be opened. Note that a glob like `release-notes/{version}-{slug}-*` matches + the component branches but **not** the base branch — verifying with that pattern reports success + while the base branch is still local-only. +2. **Confirm each component branch's parent is the base branch commit.** When it is, each component + PR shows a clean one-file diff instead of also restating the shared metadata. +3. **Open the base PR against `main`**, then the component PRs against the base branch. +4. **Verify assignees after creating each PR.** GitHub silently drops assignees who lack access to + the repo: the API returns success and the PR is created with the assignee missing. Re-read the PR + and compare against the intended list rather than trusting the exit code. + +### gh pr edit does not work on this repo + +`gh pr edit` fails against `dotnet/core` with a Projects (classic) GraphQL deprecation error and +leaves the PR unchanged. This affects the whole command, not just one flag — `--add-assignee`, +`--remove-assignee`, and `--body` / `--body-file` all fail the same way. It exits non-zero, but the +error text is about Projects rather than about what you were trying to change, so it is easy to +mistake for a warning. Use the REST endpoints: + +```bash +gh api -X POST repos/dotnet/core/issues/{number}/assignees -f "assignees[]=" +gh api -X DELETE repos/dotnet/core/issues/{number}/assignees -f "assignees[]=" + +# Editing the PR title or body +'{"body": "..."}' | gh api -X PATCH repos/dotnet/core/pulls/{number} --input - +``` + ## Merge flow Each component PR merges into the base branch. When all component PRs merge, the base PR's diff is the full milestone — there is no separate consolidation PR. +**The component owner merges their own PR.** Reviewing and approving is not enough — the owner is responsible for merging their component PR into the base branch once it's ready, rather than leaving it for someone else to merge. + ## PR title convention - Base PR: `[release-notes] .NET {version} {milestone-label}` (e.g. `[release-notes] .NET 11 Preview 4`). @@ -26,4 +59,6 @@ Each component PR merges into the base branch. When all component PRs merge, the ## Draft state -Open both the base PR and every component PR as **drafts** (`gh pr create --draft`). Component teams promote their PR to ready-for-review once they've vetted the AI-authored content (including any `` placeholders). The base PR stays a draft until the milestone ships. +Open both the base PR and every component PR as **drafts** (`gh pr create --draft`). Component teams promote their PR to ready-for-review once they've vetted the AI-authored content (including any `` placeholders), then merge it into the base branch themselves. The base PR stays a draft until the milestone ships. + +When notifying owners that their PRs are open, state that they own the merge, not just the review. diff --git a/.github/skills/validate-code-samples/SKILL.md b/.github/skills/validate-code-samples/SKILL.md new file mode 100644 index 00000000000..fc91a39ee4f --- /dev/null +++ b/.github/skills/validate-code-samples/SKILL.md @@ -0,0 +1,122 @@ +--- +name: validate-code-samples +description: Verify release notes claims by building and running them against the actual .NET build for the milestone. Covers acquiring a scoped SDK from the latest builds table linked from the dotnet/sdk repository, exercising every documented API and code sample, and catching the errors that static API verification cannot see - non-existent JavaScript APIs, inverted defaults, and runtime failures. USE FOR - validating a drafted component's release notes before the PR goes up, checking that documented samples compile and run, confirming a feature is actually reachable in the shipped build. DO NOT USE FOR - generating the API diff (use api-diff), confirming a managed API exists in a ref pack (use api-diff-validation), scoring features (use generate-features). +compatibility: Requires network access to GitHub and the public .NET build artifacts. Uses build-metadata.json for the milestone when available to confirm build provenance. Pairs with api-diff-validation, which covers the static half of the same problem. +--- + +# Validate Code Samples + +Build and run what the release notes claim. This is the **runtime verification stage** of the +pipeline, and it is the last line of defence before a component PR goes to its owner. + +[`api-verification.md`](../release-notes/references/api-verification.md) covers the *static* half of +this problem: does a managed type or member exist in the ref pack? That check is necessary and +cheap, but it is not sufficient. It cannot see JavaScript APIs, it cannot tell you what a default +value is, and it cannot tell you whether a documented sequence of calls actually works. + +## Acquiring a build + +Do not test against whatever SDK happens to be on the machine. Select an appropriate build for the +milestone from the build listings linked by the .NET SDK repository. + +### Select a build from the .NET SDK repository + +Start from the [`dotnet/sdk` Installing the SDK +section](https://github.com/dotnet/sdk#installing-the-sdk) and follow its **.NET SDK latest builds +table** link. Select the column that matches the milestone's SDK feature band or release branch, +then download the archive for the validation machine's platform. Preview notes should use the +matching preview column, not the build from `main`. + +The builds table also documents the public NuGet feed needed when development builds must acquire +runtime packs or other assets that aren't included in the SDK archive. + +### Confirm the build matches the notes + +Each build publishes a commit manifest next to the SDK: + +```text +https://ci.dot.net/public/Sdk/{sdk_version}/productCommit-win-x64.json +``` + +```json +{ + "runtime": { "commit": "e2c1e00b...", "version": "11.0.0-preview.7.26381.103" }, + "aspnetcore": { "commit": "e2c1e00b...", "version": "11.0.0-preview.7.26381.103" }, + "sdk": { "commit": "e2c1e00b...", "version": "11.0.100-preview.7.26381.103" } +} +``` + +The `commit` is the **VMR commit** the build came from. Check it against the head ref used to +generate `changes.json`. If they disagree, you are validating a different build than the one you +documented, and any "the API is missing" conclusion is unreliable. When `build-metadata.json` is +available, also compare its SDK version and VMR ref with the selected build before testing. + +### Install it scoped, not machine-wide + +Extract the archive to a scratch directory and point the environment at it. Do not install +machine-wide — a global install makes results non-reproducible and can disrupt other work on a +shared machine. + +```powershell +$root = "$env:TEMP\dotnet-p7" +Expand-Archive dotnet-sdk-*-win-x64.zip -DestinationPath $root +$env:DOTNET_ROOT = $root +$env:PATH = "$root;$env:PATH" +$env:DOTNET_MULTILEVEL_LOOKUP = "0" +dotnet --version # confirm this is the milestone build, not the machine SDK +``` + +Always print `dotnet --version` and confirm it before trusting any result. + +## What to validate + +Work through the drafted component markdown claim by claim. + +1. **Every code sample compiles.** Not "looks plausible" — actually builds against the milestone + build. A sample that does not compile is worse than no sample. +2. **Every documented default and polarity.** If the notes say a flag defaults to `true`, read the + value. Renames that invert meaning (`EnableX` becoming `DisableX`) are the highest-risk class of + change, because the name check passes while the meaning is backwards. +3. **Every JavaScript or browser-facing API.** `dotnet-inspect` cannot see these at all. Serve the + app and inspect the actual shipped script, or call the API from the page. Never document a JS API + from a PR description alone. +4. **Every documented endpoint or runtime behavior.** Request it. Record the status code. Build + success does not imply the page renders. +5. **Feature reachability.** Confirm the feature is reachable through the public surface in the + shipped build, not merely present in source. + +## Recording what you verified + +Note the build next to the claim so a reviewer can tell "this is wrong" apart from "this was checked +against a stale build": + +```markdown + +``` + +For samples that assert a specific runtime result, keep the expected result in the sample itself +(a header comment recording the expected HTTP status, for example) so drift shows up the next time +the sample is run. + +## When a claim fails validation + +Follow the escalation in +[`api-verification.md`](../release-notes/references/api-verification.md) — check the package version, +search for a rename, look for a revert, confirm the member is public. Then: + +- **Fix the notes, not the sample**, when the notes describe an API that does not exist. Rewrite the + section around what actually shipped. +- **Fix the sample, not the notes**, when the notes are right and the sample is stale. A sample + pinned to the previous preview will fail against a rename that the notes correctly documented. +- **Drop the claim** when neither holds up. A correct prose description with a PR link always beats a + confident, wrong code sample. + +## Notes + +- **Do not delegate this to a sub-agent.** Verification depends on reading real command output and + reacting to it. Summarizing agents reliably report that samples "look correct" - the failures in + the table above were all found by running the code directly. +- **A maintained samples repository is the cheapest way to run this stage.** Upgrading an existing + set of working samples to the new build surfaces renames, inverted defaults, and new analyzer + diagnostics as build errors and warnings, which is exactly the + [upgrade guidance](../release-notes/references/format-template.md) preview users need.