diff --git a/.github/instructions/nuget-package-structure.instructions.md b/.github/instructions/nuget-package-structure.instructions.md
new file mode 100644
index 0000000000..bb8ad2403e
--- /dev/null
+++ b/.github/instructions/nuget-package-structure.instructions.md
@@ -0,0 +1,81 @@
+---
+applyTo: "**/nuspec,**/build.proj,**/ref/**"
+---
+# NuGet Package Structure — Microsoft.Data.SqlClient
+
+This document describes the folder layout of the generated `Microsoft.Data.SqlClient` NuGet package, what each folder holds, and how runtime resolution works.
+
+## Package Resolution Overview
+
+- **`ref/`** — Used at **compile time only**. Thin assemblies with `throw null` bodies defining the public API surface. NuGet selects the best-matching TFM.
+- **`runtimes/{rid}/lib/`** — Used at **runtime** when the host OS RID matches. Contains full implementations with OS-specific code. These **override** the corresponding `lib/` assemblies.
+- **`lib/`** — Used at **runtime** as a **fallback** when no RID-specific match exists in `runtimes/`. For `net462` this is the real implementation. For `net8.0`/`net9.0` these are AnyOS stubs. For `netstandard2.0` this is the only runtime target.
+
+## Folder Structure
+
+```
+Microsoft.Data.SqlClient.nupkg
+│
+├── ref/ # Compile-time reference assemblies (throw null bodies, no real implementation)
+│ ├── net462/ # Built from netfx/ref, Windows_NT
+│ │ ├── Microsoft.Data.SqlClient.dll # NetFx ref assembly — public API surface for .NET Framework
+│ │ └── Microsoft.Data.SqlClient.xml # XML doc comments for IntelliSense
+│ ├── net8.0/ # Built from netcore/ref, AnyOS
+│ │ ├── Microsoft.Data.SqlClient.dll # NetCore ref assembly — public API surface for .NET 8
+│ │ └── Microsoft.Data.SqlClient.xml # XML doc comments for IntelliSense
+│ ├── net9.0/ # Built from netcore/ref, AnyOS
+│ │ ├── Microsoft.Data.SqlClient.dll # NetCore ref assembly — public API surface for .NET 9
+│ │ └── Microsoft.Data.SqlClient.xml # XML doc comments for IntelliSense
+│ └── netstandard2.0/ # Built from netcore/ref, AnyOS
+│ ├── Microsoft.Data.SqlClient.dll # NetStandard ref assembly — public API surface for netstandard2.0
+│ └── Microsoft.Data.SqlClient.xml # XML doc comments for IntelliSense
+│
+├── lib/ # Default runtime assemblies (used when no RID-specific match in runtimes/)
+│ ├── net462/ # Built from netfx/src, Windows_NT
+│ │ ├── Microsoft.Data.SqlClient.dll # Full .NET Framework implementation (Windows-only)
+│ │ ├── Microsoft.Data.SqlClient.pdb # Debug symbols
+│ │ ├── Microsoft.Data.SqlClient.xml # XML doc comments
+│ │ └── {locale}/ # cs, de, es, fr, it, ja, ko, pl, pt-BR, ru, tr, zh-Hans, zh-Hant
+│ │ └── Microsoft.Data.SqlClient.resources.dll # Localized satellite resource DLLs
+│ ├── net8.0/ # Built from netcore/src, OSGroup=AnyOS
+│ │ ├── Microsoft.Data.SqlClient.dll # AnyOS stub — generated via GenAPI/NotSupported.targets
+│ │ ├── Microsoft.Data.SqlClient.pdb # Debug symbols
+│ │ ├── Microsoft.Data.SqlClient.xml # XML doc comments (from Windows build)
+│ │ └── {locale}/ # Localized satellite resource DLLs (from Windows build)
+│ │ └── Microsoft.Data.SqlClient.resources.dll
+│ ├── net9.0/ # Built from netcore/src, OSGroup=AnyOS
+│ │ ├── Microsoft.Data.SqlClient.dll # AnyOS stub — same as net8.0
+│ │ ├── Microsoft.Data.SqlClient.pdb # Debug symbols
+│ │ ├── Microsoft.Data.SqlClient.xml # XML doc comments (from Windows build)
+│ │ └── {locale}/ # Localized satellite resource DLLs (from Windows build)
+│ │ └── Microsoft.Data.SqlClient.resources.dll
+│ └── netstandard2.0/ # Built from netcore/ref with BuildForLib=true, AnyOS
+│ ├── Microsoft.Data.SqlClient.dll # ⚠️ Currently a ref assembly (throw null bodies) — see known issue below
+│ ├── Microsoft.Data.SqlClient.pdb # Debug symbols
+│ └── Microsoft.Data.SqlClient.xml # XML doc comments
+│
+└── runtimes/ # RID-specific runtime assemblies (override lib/ when RID matches)
+ ├── win/lib/ # Windows-specific implementations (native SNI)
+ │ ├── net462/
+ │ │ ├── Microsoft.Data.SqlClient.dll # Full .NET Framework impl (same as lib/net462)
+ │ │ └── Microsoft.Data.SqlClient.pdb # Debug symbols
+ │ ├── net8.0/
+ │ │ ├── Microsoft.Data.SqlClient.dll # Full .NET 8 impl compiled for Windows_NT
+ │ │ └── Microsoft.Data.SqlClient.pdb # Debug symbols
+ │ └── net9.0/
+ │ ├── Microsoft.Data.SqlClient.dll # Full .NET 9 impl compiled for Windows_NT
+ │ └── Microsoft.Data.SqlClient.pdb # Debug symbols
+ └── unix/lib/ # Unix/Linux/macOS implementations (managed SNI)
+ ├── net8.0/
+ │ ├── Microsoft.Data.SqlClient.dll # Full .NET 8 impl compiled for Unix
+ │ └── Microsoft.Data.SqlClient.pdb # Debug symbols
+ └── net9.0/
+ ├── Microsoft.Data.SqlClient.dll # Full .NET 9 impl compiled for Unix
+ └── Microsoft.Data.SqlClient.pdb # Debug symbols
+```
+
+## Known Issue: `lib/netstandard2.0/` Assembly
+
+The `lib/netstandard2.0/` DLL is intended to be a `PlatformNotSupportedException` stub for unsupported platforms. However, it is built by the `BuildNetStandard` target, which builds the **ref project** (`netcore/ref/`) with `BuildForLib=true` and `OSGroup=AnyOS`.
+
+The `NotSupported.targets` file is imported, but its logic is gated on `GeneratePlatformNotSupportedAssemblyMessage` being set — a property that only the **src project** (`netcore/src/`) defines. Since the ref project never sets it, the `GenerateNotSupportedSource` target is inert, and the output is just the ref assembly with `throw null` bodies instead of a proper `PlatformNotSupportedException` stub.
diff --git a/.github/plans/auto-generate-ref-assemblies.md b/.github/plans/auto-generate-ref-assemblies.md
new file mode 100644
index 0000000000..e9475bae13
--- /dev/null
+++ b/.github/plans/auto-generate-ref-assemblies.md
@@ -0,0 +1,78 @@
+# Plan: Auto-Generate Ref Assemblies from Unified Src Project
+
+## Summary
+
+Enable `ProduceReferenceAssembly` in the unified src project so ref assemblies are compiler-generated during normal builds. Create a small dedicated project for `PlatformNotSupportedException` stubs. Use `Microsoft.DotNet.ApiCompat.Tool` to compare auto-generated ref assemblies against the checked-in ref sources as a baseline. Update the nuspec to consume artifacts from the new output paths.
+
+## Phase 1: Enable auto-generated ref assemblies
+
+1. In `src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj`, add two properties:
+ - `true` (for all TFMs, including net462 which doesn't default to true)
+ - `true` (so XML docs are generated alongside the build)
+
+2. Add a post-build target in the unified csproj (or a new `.targets` file imported by it) that copies the ref assembly from `$(IntermediateOutputPath)ref/$(TargetFileName)` to `$(OutputPath)ref/$(TargetFileName)`. The SDK only places the ref DLL in the intermediate `obj/` directory — this copy step puts it alongside the main assembly output at a predictable location like `artifacts/Microsoft.Data.SqlClient/{Config}/{os}/{tfm}/ref/Microsoft.Data.SqlClient.dll`.
+
+3. Also copy the generated XML doc file (`$(OutputPath)$(AssemblyName).xml`) to `$(OutputPath)ref/$(AssemblyName).xml` so the ref assembly has companion IntelliSense XML in the same directory.
+
+4. Import `tools/targets/TrimDocsForIntelliSense.targets` in the unified src project to trim the XML doc file to only public API content (removing docs for internal/private members that the compiler includes).
+
+## Phase 2: Create a dedicated PNSE stub project
+
+5. Create a new project at `src/Microsoft.Data.SqlClient/notsupported/Microsoft.Data.SqlClient.NotSupported.csproj` targeting `net8.0;net9.0;netstandard2.0`. This project:
+ - Sets `Microsoft.Data.SqlClient is not supported on this platform.`
+ - Sets `Microsoft.Data.SqlClient` (same assembly name as the real one)
+ - Imports `tools/targets/ResolveContract.targets` and `tools/targets/NotSupported.targets`
+ - Points `ContractAssemblyPath` to the ref assembly produced by Phase 1 (for net8.0 or net9.0), or adds a `ProjectReference` to the unified src project with `OutputItemType=ResolvedMatchingContract` and `ReferenceOutputAssembly=false`
+ - GenAPI reads the ref assembly, generates `.notsupported.cs` source with `PlatformNotSupportedException` bodies, and the project compiles it into DLLs for all three TFMs
+ - Output goes to a well-known path (e.g., `artifacts/Microsoft.Data.SqlClient/{Config}/anyos/`)
+
+6. Update `tools/targets/ResolveContract.targets` if needed — the current `ContractProject` default points to the legacy `netcore/ref/` project. The new PNSE project should either override `ContractProject` to point to the unified src project, or set `ContractAssemblyPath` directly to the Phase 1 ref assembly output.
+
+## Phase 3: API compat checking
+
+7. Add `Microsoft.DotNet.ApiCompat.Tool` to `dotnet-tools.json` as a local dotnet tool. This provides the `dotnet apicompat` command.
+
+8. Create a new MSBuild target (e.g., `ValidateApiCompat` in a `.targets` file or in `build.proj`) that:
+ - Builds the existing checked-in ref project at `src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.csproj` to produce baseline ref DLLs (for net462, net8.0, net9.0)
+ - Runs `dotnet apicompat` comparing the auto-generated ref assemblies (from Phase 1) against these baseline DLLs
+ - Fails the build if breaking changes are detected (new APIs are allowed; removed/changed APIs are errors)
+ - This target should run as part of CI but be opt-in for local development (e.g., gated on a property like `ValidateApi=true`)
+
+9. The checked-in ref sources at `src/Microsoft.Data.SqlClient/ref/` remain in the repo as the API baseline. They are no longer used for packaging — only for compat validation. Later, these can be replaced with a baseline from the last published NuGet package.
+
+## Phase 4: Update build infrastructure
+
+10. Update `build.proj` targets:
+ - The `BuildNetCoreAllOS` target's AnyOS invocation (line 232) should build the new PNSE project instead of the legacy `netcore/src` with `OSGroup=AnyOS`
+ - The `BuildNetStandard` target (line 241-242) should also use the PNSE project instead of the legacy `netcore/ref` with `BuildForLib=true`
+ - Remove or deprecate the `OSGroup=AnyOS` invocation of `@(NetCoreDriver)` — it's replaced by the PNSE project
+ - Add a new target (e.g., `BuildNotSupported`) that builds the PNSE project
+
+11. Update `tools/specs/Microsoft.Data.SqlClient.nuspec` source paths:
+ - **`ref/net462/`**: Change from `artifacts/$ReferenceType$/bin/Windows_NT/{Config}/Microsoft.Data.SqlClient/ref/net462/` → `artifacts/Microsoft.Data.SqlClient/{Config}/windows_nt/net462/ref/`
+ - **`ref/net8.0/`**: Change from `artifacts/$ReferenceType$/bin/AnyOS/{Config}/Microsoft.Data.SqlClient/ref/net8.0/` → `artifacts/Microsoft.Data.SqlClient/{Config}/windows_nt/net8.0/ref/` (ref assemblies are OS-independent; use Windows build output)
+ - **`ref/net9.0/`**: Same pattern as net8.0
+ - **`ref/netstandard2.0/`**: Remove (no separate ref assembly for netstandard2.0 since the unified src project doesn't target it; the PNSE stub in `lib/netstandard2.0/` serves as the netstandard2.0 surface)
+ - **`lib/net8.0/`** and **`lib/net9.0/`** (AnyOS stubs): Change to point to the PNSE project output
+ - **`lib/netstandard2.0/`**: Change to point to the PNSE project output
+ - Keep `lib/net462/`, `runtimes/win/`, and `runtimes/unix/` paths pointing to unified src project output
+
+12. Verify that the `ref/netstandard2.0/` slot in the nuspec is still needed. If the package has `lib/netstandard2.0/` (the PNSE stub), NuGet may need a matching `ref/netstandard2.0/` for compile-time. Options:
+ - Use the PNSE stub DLL itself as both `ref/` and `lib/` for netstandard2.0 (since it has the right API surface)
+ - Or produce a ref assembly from the PNSE project too (via `ProduceReferenceAssembly` on the PNSE project)
+ - Or use the net8.0 ref assembly re-targeted (may cause issues)
+
+## Verification
+
+- Build the unified src project and confirm ref assemblies + XML docs appear at the expected output paths for all three TFMs (net462, net8.0, net9.0)
+- Build the PNSE project and confirm it produces `PlatformNotSupportedException` stubs for net8.0, net9.0, and netstandard2.0 — verify by decompiling or instantiating a type
+- Run `dotnet apicompat` between the auto-generated ref assemblies and the checked-in baseline — should pass with no breaking changes
+- Run `nuget pack` on the updated nuspec and verify the package structure matches the expected layout from `.github/instructions/nuget-package-structure.instructions.md`
+- Run existing unit and functional tests to ensure no regressions
+
+## Decisions
+
+- **ProduceReferenceAssembly over GenAPI for ref generation**: Chose compiler-generated ref assemblies because they are guaranteed to match the implementation's public API surface, require no manual maintenance, and preserve XML doc content from the shared `doc/snippets/` files
+- **Dedicated PNSE project over extending unified src**: Chose a separate project to keep concerns clean — the src project produces real implementations + ref assemblies, the PNSE project produces stubs. This avoids adding `AnyOS` mode complexity and `netstandard2.0` TFM to the unified src project
+- **Checked-in ref sources as baseline**: Keeps the existing hand-maintained ref `.cs` files as the API compat baseline for now, with a planned future migration to comparing against the last published NuGet package
+- **Update nuspec paths**: Chose to update the nuspec to point to the unified project's output paths rather than adding copy steps to bridge to the legacy path structure