Skip to content

Commit 47a038f

Browse files
committed
Add location-gated agent guidance
Add repository-wide instructions and scoped guidance for every source project, with Copilot using the root file as the canonical entry point. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: aaee9aa5-4a14-4da6-bf12-c8948e58e21c
1 parent 94bc75d commit 47a038f

37 files changed

Lines changed: 1583 additions & 27 deletions

File tree

.github/copilot-instructions.md

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,5 @@
11
# NuGet.Client Copilot instructions
22

3-
NuGet.Client is the .NET codebase for NuGet's client tooling and libraries across Visual Studio, the .NET CLI, MSBuild, and `nuget.exe`.
4-
5-
## Development environment
6-
7-
- Build and test only the projects relevant to the change.
8-
- On Windows:
9-
- Run `.\configure.ps1` before the first build.
10-
- Build with the `dotnet` or `msbuild` CLI.
11-
- On Linux and macOS:
12-
- Run `. ./configure.sh` before the first build. It must be sourced, not executed.
13-
- Build with `dotnet`, or run `./build.sh` to build all the cross-platform projects. Avoid building `NuGet.sln`, since it includes a few Windows-only projects.
14-
- Run `dotnet test` to execute tests. Use `--filter` to run a subset.
15-
- Use NuGet Central Package Management: declare package versions in `Directory.Packages.props` and add versionless `PackageReference` items to project files. Read the [package-update guidance](../docs/updating-packages.md) before changing dependency versions.
16-
17-
## Task-specific guidance
18-
19-
Before implementing code changes, identify and read the guidance relevant to the task. In particular:
20-
21-
- For new features and behavior changes, read the [feature guide](../docs/feature-guide.md), including its requirements for feature configuration, `SdkAnalysisLevel` gating, and restore and pack considerations.
22-
- For public API additions, changes, removals, or shipping, read the [NuGet SDK guidance](../docs/nuget-sdk.md).
23-
- For C# implementation and error-handling patterns, read the [C# conventions and guidelines](agent_docs/csharp.md).
24-
- For localized resources, read the [localization guidance](agent_docs/localization.md).
25-
- For nullable migrations, read the [nullable migration guidance](agent_docs/nullable-migrations.md).
26-
- For performance measurements, read the [benchmarking guidance](agent_docs/benchmarking.md).
27-
- Before creating a branch or pull request, read the [Git and pull request guidance](agent_docs/git-workflow.md).
28-
29-
The repository's broader development documentation is indexed in [CONTRIBUTING.md](../CONTRIBUTING.md).
3+
Read and follow [`../AGENTS.md`](../AGENTS.md) before making changes.
4+
The root file is the canonical repository-wide guidance; the nearest nested
5+
`AGENTS.md` applies additional instructions for files in its subtree.

AGENTS.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# NuGet.Client agent instructions
2+
3+
NuGet.Client is the .NET codebase for NuGet tooling and libraries used by
4+
Visual Studio, the .NET CLI, MSBuild, and `nuget.exe`.
5+
6+
## Scope and precedence
7+
8+
- These instructions apply to the entire repository.
9+
- Read and follow the nearest nested `AGENTS.md` for the files being changed.
10+
- Preserve user changes and do not modify unrelated files.
11+
- Prefer the smallest complete change that addresses the root cause.
12+
13+
## Before making changes
14+
15+
1. Inspect the affected projects and tests, and search for existing patterns
16+
before adding new helpers or abstractions.
17+
2. Read the guidance relevant to the task:
18+
19+
| Change | Required guidance |
20+
| --- | --- |
21+
| New feature or behavior change | [`docs/feature-guide.md`](docs/feature-guide.md) |
22+
| Public API change | [`docs/nuget-sdk.md`](docs/nuget-sdk.md) |
23+
| C# implementation | [`.github/agent_docs/csharp.md`](.github/agent_docs/csharp.md) |
24+
| Localization | [`.github/agent_docs/localization.md`](.github/agent_docs/localization.md) |
25+
| Nullable migration | [`.github/agent_docs/nullable-migrations.md`](.github/agent_docs/nullable-migrations.md) |
26+
| Performance measurement | [`.github/agent_docs/benchmarking.md`](.github/agent_docs/benchmarking.md) |
27+
| Dependency update | [`docs/updating-packages.md`](docs/updating-packages.md) |
28+
| Branch or pull request | [`.github/agent_docs/git-workflow.md`](.github/agent_docs/git-workflow.md) |
29+
30+
3. Use [`CONTRIBUTING.md`](CONTRIBUTING.md) as the index for broader
31+
development documentation.
32+
33+
## Implementation rules
34+
35+
- Follow existing project conventions and reuse established test utilities.
36+
- Add or update tests when behavior changes.
37+
- Consider all affected NuGet surfaces: Visual Studio, `dotnet`, MSBuild,
38+
`nuget.exe`, restore, and pack. Change only the surfaces relevant to the task.
39+
- Follow `SdkAnalysisLevel` and feature-configuration requirements for new
40+
behavior.
41+
- Keep public API files accurate when changing public surface area.
42+
- Declare package versions in `Directory.Packages.props`; project
43+
`PackageReference` items must be versionless.
44+
- Do not edit generated localization `.xlf` files manually. Edit the `.resx`
45+
and build the owning project to regenerate dependent files.
46+
47+
## Build and test
48+
49+
- Configure once before the first build:
50+
- Windows: `.\configure.ps1`
51+
- Linux or macOS: `. ./configure.sh`
52+
- Build only the projects relevant to the change with `dotnet` or `msbuild`.
53+
- On Linux and macOS, do not build `NuGet.sln`; it contains Windows-only
54+
projects. Use `./build.sh` when a broader cross-platform build is needed.
55+
- Run the smallest relevant tests with `dotnet test`, using `--filter` when
56+
possible.
57+
- Before submitting a pull request, run:
58+
`dotnet format whitespace --verify-no-changes NuGet.sln`
59+
60+
## Completion
61+
62+
- Ensure source, tests, public API files, generated artifacts, and directly
63+
related documentation remain consistent.
64+
- Report the files changed and the exact validation performed.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# NuGet.CommandLine Agent Scope
2+
3+
## Architecture
4+
5+
NuGet.CommandLine is a single Windows desktop executable (`NuGet.exe`) using MEF for command composition and ILRepack for binary merging. Commands are discovered via `[Import]`/`[ImportMany]` attributes (CommandManager.cs). Extensions load from `%LocalAppData%\NuGet\{Commands,CredentialProviders}` or paths set via environment variables `NUGET_EXTENSIONS_PATH` and `NUGET_CREDENTIALPROVIDERS_PATH`.
6+
7+
**Supported Windows versions:** Windows 7, 8, 8.1, 10 (app.manifest).
8+
**Build target:** .NET Framework 4.6.2+.
9+
**Output:** ILRepack-merged executable with embedded localized satellites (13 languages).
10+
11+
## High-Risk Invariants
12+
13+
1. **ILRepack determinism**: Binary merge order is significant; NuGet.Core.dll must be last (ilmerge.props, csproj). Test: `dotnet build src\NuGet.Clients\NuGet.CommandLine\NuGet.CommandLine.csproj`
14+
2. **Localization satellites**: Embedded resource DLLs only in CI builds (csproj); local debug builds skip them.
15+
3. **Extension discovery order**: Environment variables checked before default paths; tests must disable extensions via `Program.IgnoreExtensions = true`.
16+
4. **Command lookup**: Case-insensitive prefix matching with ambiguity detection (CommandManager.GetCommand); exact matches preferred.
17+
18+
## Test Execution
19+
20+
**Unit tests:**
21+
```cmd
22+
dotnet test test\NuGet.Clients.Tests\NuGet.CommandLine.Test\NuGet.CommandLine.Test.csproj --filter "Category!=Integration"
23+
```
24+
25+
**Functional tests:**
26+
```cmd
27+
dotnet test test\NuGet.Clients.FuncTests\NuGet.CommandLine.FuncTest\NuGet.CommandLine.FuncTest.csproj
28+
```
29+
30+
**Extension loading tests:** Verify SampleCommandLineExtensions (TestExtensions directory) is copied to test output before running extension-related tests.
31+
32+
## Build
33+
34+
```cmd
35+
dotnet build src\NuGet.Clients\NuGet.CommandLine\NuGet.CommandLine.csproj
36+
```
37+
38+
Produces `bin/Configuration/net462/NuGet.exe` (pre-merge); post-build target `ILMergeNuGetExe` produces `artifacts/NuGet.exe`.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# NuGet.Console Agent Scoping
2+
3+
## Ownership
4+
`src\NuGet.Clients\NuGet.Console\` — VSIX-bundled PowerShell console UI for Package Manager (WPF, .NET Framework only).
5+
6+
## Architecture Invariants
7+
- **MEF Composition**: Exports `IPowerConsoleWindow`, `IWpfConsoleService`, `IScriptExecutor` via `[Export]` attributes; multi-host via `[ImportMany] IHostProvider`.
8+
- **UI-Thread Gating**: All cross-process calls marshal via `NuGetUIThreadHelper.JoinableTaskFactory` and VS `ThreadHelper.ThrowIfNotOnUIThread()`. Violations cause deadlock/hang.
9+
- **PowerShell 3.x Host**: `ScriptExecutor` wraps init.ps1 execution; async events trigger console prompt refresh. `IPSNuGetProjectContext` bridges PS session state.
10+
- **Output Interop**: `OutputConsole` (non-blocking) and `BuildOutputConsole` write to VS Output pane via `IVsOutputWindow` — thread-safe by AsyncLazy marshaling.
11+
- **Dispatcher Concurrency**: `ConsoleDispatcher` uses `BlockingCollection<VsKeyInfo>` for input buffering; `ConcurrentDictionary` tracks init.ps1 per-package state.
12+
13+
## High-Risk Edits
14+
- Change `AsyncLazy` initialization pattern → UI hangs.
15+
- Remove JoinableTaskFactory marshaling → cross-thread access violation.
16+
- Modify MEF metadata/export names → composition fails silently.
17+
- Add Thread.Sleep or blocking I/O in dispatcher → keyboard unresponsive.
18+
19+
## Matching Tests
20+
- **Unit**: `test\NuGet.Clients.Tests\NuGetConsole.Host.PowerShell.Test\` — cmdlet + runspace tests.
21+
- **Contract**: `test\NuGet.Tests.Apex\NuGet.Console.TestContract\` — APEX integration tests (requires VS).
22+
- **Logger**: `test\NuGet.Clients.Tests\NuGet.VisualStudio.Common.Test\OutputConsoleLoggerTests*.cs` — output pane logging.
23+
24+
## Validation Commands
25+
```
26+
dotnet build src\NuGet.Clients\NuGet.Console\NuGet.Console.csproj
27+
dotnet test test\NuGet.Clients.Tests\NuGetConsole.Host.PowerShell.Test\ --logger=console
28+
dotnet build /p:IncludeInVSIX=true src\NuGet.Clients\NuGet.Console\NuGet.Console.csproj
29+
```
30+
31+
## Dependencies
32+
- `Microsoft.VisualStudio.Sdk`, `Microsoft.PowerShell.3.ReferenceAssemblies`
33+
- `NuGet.PackageManagement.UI`, `NuGet.VisualStudio` (transitive)
34+
- Win-only; requires VS 2015+; no Mono/CoreCLR support.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# NuGet.Indexing
2+
3+
Package search indexing and ranking for Visual Studio client.
4+
5+
## Architecture
6+
7+
**Query Flow**: Query string → NuGetQuery.MakeQuery() → Lucene BooleanQuery
8+
- Field keywords: `id`, `version`, `title`, `description`, `tag/tags`, `author/authors`, `summary`, `owner/owners`
9+
- Quoted phrases supported; unquoted tokens become wildcard
10+
11+
**Indexing**: PackageAnalyzer wraps field-specific analyzers
12+
- `Id`, `TokenizedId`, `ShingledId`: IdentifierKeywordAnalyzer, IdentifierAnalyzer
13+
- `Title`, `Description`, `Summary`, `Authors`: DescriptionAnalyzer
14+
- `Version`: VersionAnalyzer (semantic)
15+
- `Tags`: TagsAnalyzer; `Owner`: OwnerAnalyzer
16+
17+
**Ranking Pipeline**
18+
1. RelevanceSearchResultsIndexer.Rank() creates in-memory Lucene index from IPackageSearchMetadata entries
19+
2. Executes query, scores results, maps by package ID to rank dict
20+
3. ProcessUnrankedEntries() fills gaps: unranked entries inherit prior ranked entry's rank, fallback to -1
21+
22+
**Result Aggregation**: SearchResultsAggregator merges multiple search results
23+
- Requires ISearchResultsIndexer (ranking) + IPackageSearchMetadataSplicer (merge strategy)
24+
- Preserves input relative order per feed; re-ranks merged set
25+
26+
## High-Risk Invariants
27+
28+
**PackageSearchMetadataSplicer.MergeEntries(lhs, rhs)**
29+
- Throws InvalidOperationException if lhs.Identity.Id ≠ rhs.Identity.Id (case-insensitive)
30+
- Picks newer version as base; merges version lists via GetVersionsAsync()
31+
- Validates before merge; no partial state on exception
32+
33+
**RelevanceSearchResultsIndexer.Rank()**
34+
- Lucene RAMDirectory is in-memory only; index lifecycle tied to indexer call
35+
- Ranking dict uses case-sensitive package IDs (retrieved from Lucene Field "Id")
36+
- Default rank for unranked entries: -1
37+
38+
## Build & Test
39+
40+
```powershell
41+
# Build
42+
dotnet build src\NuGet.Clients\NuGet.Indexing\NuGet.Indexing.csproj
43+
44+
# Test all
45+
dotnet test test\NuGet.Clients.Tests\NuGet.Indexing.Test\NuGet.Indexing.Test.csproj -v normal
46+
47+
# Test by name
48+
dotnet test test\NuGet.Clients.Tests\NuGet.Indexing.Test\NuGet.Indexing.Test.csproj --filter MergeEntries_WithDifferentPackageIds_Throws
49+
dotnet test test\NuGet.Clients.Tests\NuGet.Indexing.Test\NuGet.Indexing.Test.csproj --filter AggregateAsync_MergesVersions
50+
dotnet test test\NuGet.Clients.Tests\NuGet.Indexing.Test\NuGet.Indexing.Test.csproj --filter ProcessUnrankedEntries_FillsWithDefaultRank
51+
```
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# AGENTS.md: NuGet.MSSigning.Extensions
2+
3+
**Scope:** `src\NuGet.Clients\NuGet.MSSigning.Extensions`
4+
5+
## Architecture
6+
- **Commands:** `MSSignCommand` (author signing), `RepoSignCommand` (repo signing)
7+
- **Base:** `MSSignAbstract` — validates X.509 cert fingerprints (SHA-256/384/512), retrieves RSA private key via `CngProvider`
8+
- **Output:** ILMerge'd `NuGet.Mssign.exe` from 34 dependent assemblies (see `ilmerge.props`)
9+
- **Framework:** net472 | **Shipping:** true | **Sign:** Microsoft key + delay-sign
10+
11+
## High-Risk Invariants
12+
- **CNG Provider constraint** (MSSignAbstract.cs): `CngKey.Open(keyContainer, provider, CngKeyOpenOptions.MachineKey)` requires Windows registry/HSM. Cross-platform tests must skip.
13+
- **Cert validation** (MSSignAbstract.cs): SHA-1 fingerprints rejected; deduction logic skips SHA-1 branch only for Thumbprint match.
14+
- **ILMerge post-build** (NuGet.MSSigning.Extensions.csproj): Runs only when `BuildingInsideVisualStudio != 'true'`. SignWithMicrosoftKey enforced via delay-sign keyfile.
15+
16+
## Matching Tests
17+
| Type | Project Path | Entry Tests |
18+
|------|--------------|-------------|
19+
| Unit | `test\NuGet.Clients.Tests\NuGet.MSSigning.Extensions.Test` | `NuGetMSSignCommandTest.cs`, `NuGetReposignCommandTest.cs` |
20+
| Functional | `test\NuGet.Clients.FuncTests\NuGet.MSSigning.Extensions.FuncTest` | `MSSignCommandTests.cs`, `ReposignCommandTests.cs` |
21+
22+
## Validation Commands
23+
```batch
24+
:: Build extension DLL and ILMerge executable
25+
dotnet build src\NuGet.Clients\NuGet.MSSigning.Extensions\NuGet.MSSigning.Extensions.csproj
26+
27+
:: Unit tests (cross-platform compatible)
28+
dotnet test test\NuGet.Clients.Tests\NuGet.MSSigning.Extensions.Test --logger:console
29+
30+
:: Functional tests (Windows + admin required; modifies LocalMachine\Root cert store)
31+
dotnet test test\NuGet.Clients.FuncTests\NuGet.MSSigning.Extensions.FuncTest --logger:console
32+
33+
:: Verify ILMerge artifact
34+
powershell -NoProfile -Command "Test-Path artifacts\VSIX\NuGet.Mssign.exe"
35+
```
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# AGENTS.md: NuGet.PackageManagement.PowerShellCmdlets
2+
3+
**Owns:** Package Manager Console PowerShell host + 9 NuGet cmdlets (Find-Package, Get-Package, Install-Package, Update-Package, Uninstall-Package, Add-BindingRedirect, Get-Project, Sync-Package, Tab Expansion).
4+
5+
**Target Framework:** net472 only (no cross-platform). PowerShell 2.0+ manifest. Visual Studio-bound via DTE automation.
6+
7+
## High-Risk Invariants
8+
9+
1. **Runspace Threading Lock (net472 only):**
10+
- RunspaceDispatcher.WithLock() uses SemaphoreSlim(1,1) + [ThreadStatic] IHaveTheLock
11+
- All pipeline invocations (sync/async) must serialize through this lock
12+
- **Violation:** Direct Runspace.Invoke() outside WithLock = deadlock or race
13+
- **Validation:** dotnet build src\NuGet.Clients\NuGet.PackageManagement.PowerShellCmdlets\NuGet.PackageManagement.PowerShellCmdlets.csproj -c Release
14+
15+
2. **Satellite Assembly Generation:**
16+
- 13 XLF files → satellite DLLs via GenerateSatelliteAssembliesForCore=true
17+
- Missing XLF = missing language pack
18+
- Build the project to regenerate and validate satellite assemblies.
19+
20+
3. **Manifest Module Update:**
21+
- Post-build target runs UpdateNuGetModuleManifest.ps1 to patch NuGet.psd1 with runtime FullName
22+
- Script validates **exactly one** occurrence of 'NuGet.PackageManagement.PowerShellCmdlets.dll' and fails on mismatch
23+
- **Validation:** Build output captures manifest patching success
24+
25+
4. **UI Thread Barrier:**
26+
- ThreadHelper.ThrowIfOnUIThread() enforces runspace operations off-UI-thread
27+
- Cmdlet base class (NuGetPowerShellBaseCommand) must not call UI methods directly
28+
- **Validation:** Code review + test fixture usage
29+
30+
## Matching Tests
31+
32+
**Project:** `test\NuGet.Clients.Tests\NuGetConsole.Host.PowerShell.Test\`
33+
**Test Commands:**
34+
- dotnet test test\NuGet.Clients.Tests\NuGetConsole.Host.PowerShell.Test\NuGetConsole.Host.PowerShell.Test.csproj -c Release --logger "console;verbosity=detailed"
35+
- Filter by fixture: --filter "GetPackageCommandTests"
36+
37+
**Key Fixtures:**
38+
- CmdletRunspaceFixture (isolated runspace, minimal PSHost)
39+
- GetPackageCommandTests, FindPackageCommandTests (async cmdlet execution)
40+
41+
## Build & Validation
42+
43+
```powershell
44+
# Full build
45+
dotnet build src\NuGet.Clients\NuGet.PackageManagement.PowerShellCmdlets\NuGet.PackageManagement.PowerShellCmdlets.csproj -c Release
46+
47+
# Test coverage
48+
dotnet test test\NuGet.Clients.Tests\NuGetConsole.Host.PowerShell.Test\NuGetConsole.Host.PowerShell.Test.csproj -c Release
49+
50+
# Verify satellite assemblies
51+
Get-ChildItem src\NuGet.Clients\NuGet.PackageManagement.PowerShellCmdlets\bin\Release\net472\*/NuGet.PackageManagement.PowerShellCmdlets.resources.dll
52+
```
53+
54+
## Constraints & Assumptions
55+
56+
- **No async/await in cmdlet implementations:** BlockingCollection + Semaphore enforce sync dispatch
57+
- **Localization immutable post-build:** XLF files frozen; manifest auto-patches only assembly identity
58+
- **Test isolation:** CmdletRunspaceFixture creates fresh runspace per test (no state leakage)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# AGENTS.md: NuGet.PackageManagement.UI
2+
3+
**Scope:** `src\NuGet.Clients\NuGet.PackageManagement.UI` — Visual Studio Package Manager UI, tool windows, dialogs, package metadata.
4+
5+
## Architecture
6+
7+
- **PackageManagerControl**: Main WPF UserControl (IVsWindowSearch, IPackageManagerControlViewModel)
8+
- **PackageManagerToolWindowPane**: VS ToolWindowPane host (IVsWindowFrameNotify3)
9+
- **Threading Model**: Mandatory `NuGetUIThreadHelper.JoinableTaskFactory` for all async operations
10+
- RunAsync() for fire-and-forget background tasks
11+
- SwitchToMainThreadAsync() for UI marshaling
12+
- Run() for sync-over-async blocking
13+
- **XAML Layers**: 32 XAML files (controls, dialogs, indicators); theme/brush resources via DynamicResource
14+
- **Accessibility**: Custom AutomationPeers (ButtonHyperlinkAutomationPeer, ToggleableItemAutomationPeer implementing IToggleProvider)
15+
- **Localization**: 13 XLF satellite resources; Resources.resx with PublicResXFileCodeGenerator; T4 template for PackageIconMonikers
16+
- **Target**: .NET Framework (NETFXTargetFramework); requires PresentationFramework, System.Runtime.Caching
17+
- **Tests**: test\NuGet.Clients.Tests\NuGet.PackageManagement.UI.Test with WpfFactAttribute/WpfTheoryAttribute custom xunit discoverers
18+
19+
## High-Risk Invariants
20+
21+
1. **All background operations must use NuGetUIThreadHelper.JoinableTaskFactory**: Failure causes UI thread hangs or race conditions in VS event handlers.
22+
2. **No direct ThreadPool.QueueUserWorkItem or Task.Run without JoinableTaskFactory**: Blocks VS shutdown and breaks modal dialogs.
23+
3. **AutomationPeer implementations must preserve inheritance chain**: Custom peers override CreateItemAutomationPeer() to ensure accessibility tree consistency.
24+
4. **XAML resources must use ImageThemingUtilities for theme colors**: Missing themes break dark/light mode transitions.
25+
5. **Localization is generated from Resources.resx**: Edit the `.resx`, then build the project to regenerate the designer and `.xlf` files.
26+
27+
## Build & Test Commands
28+
29+
```powershell
30+
# Build
31+
dotnet build src\NuGet.Clients\NuGet.PackageManagement.UI\NuGet.PackageManagement.UI.csproj -c Release
32+
33+
# Run all UI tests
34+
dotnet test test\NuGet.Clients.Tests\NuGet.PackageManagement.UI.Test\NuGet.PackageManagement.UI.Test.csproj --no-build
35+
36+
# Run specific WPF test
37+
dotnet test test\NuGet.Clients.Tests\NuGet.PackageManagement.UI.Test\NuGet.PackageManagement.UI.Test.csproj --filter "FullyQualifiedName~PackageItemLoaderTests" --no-build
38+
```

0 commit comments

Comments
 (0)