| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 14 | 4 | 0% |
| Commands | 0 | 0 | 4 | 0% |
| Section tags | 3 | 4 | 3 | 30% |
What each file covers
Sections
0 shared · 14 only in A · 4 only in B- − C# (managed code)
- − Correctness & Safety
- − Error Handling & Assertions
- − Thread Safety
- − Security
- − Correctness Patterns
- − Performance & Allocations
- − Measurement & Evidence
- − Allocation Avoidance
- − Code Structure for Performance
- − Specific API Choices
- − API Design & Contracts
- − Code Style & Formatting
- − Platform & Cross-Platform
- + Pull Requests
- + AI-Generated Content Disclosure
- + Tool Use
- + Building & Testing
Commands
0 shared · 0 only in A · 4 only in B- + gh run view --log-failed
- + git diff --stat
- + git clone
- + dotnet
Section tags
3 shared · 4 only in A · 3 only in B- − lint-format
- − security
- − api
- − performance
- + build
- + test
- + git-pr
- code-style
- architecture
- do-not
Line diff
dotnet/runtime · .github/instructions/csharp.instructions.md
@@ −1 @@
1---
2applyTo: "**/*.cs"
3---
4
5# C# (managed code)
6
7Conventions for C# changes across `src/`. Also apply `conventions` (all changes), `tests` (test
8files), and any matching area file (`core-runtime`, `jit`, `system-net-*`, `extensions-*`,
9`compression`, `cdac`). Native runtime code is covered by `native`.
10
11## Correctness & Safety
12
13### Error Handling & Assertions
14
15- **Use `Debug.Assert` for internal invariants, not exceptions.** For internal-only callers, assert assumptions rather than throwing `ArgumentException`. Prefer `Debug.Assert(value is not null)` over the null-forgiving operator (`!`).
16- **Use `throw` for reachable error paths, `UnreachableException` for exhaustive switches.** When a code path might be hit at runtime, throw an exception rather than asserting. Use `throw new UnreachableException()` for default cases in exhaustive switches. Use `PlatformNotSupportedException` (not `NotSupportedException`) for platform gaps.
17- **Include actionable details in exception messages.** Use `nameof` for parameter names. Include the unsupported type or unexpected value. Never throw empty exceptions.
18- **Initialize output parameters in all code paths.** When a method has `out` parameters or pointer outputs (`bytesWritten`, `numLocals`), ensure they are initialized to a defined value in all error paths.
19- **Use `ThrowIf` helpers over manual checks.** Use `ArgumentOutOfRangeException.ThrowIfNegative`, `ObjectDisposedException.ThrowIf`, etc. instead of manual if-then-throw patterns.
20- **Don't swallow exceptions that mask unexpected errors.** Before adding a try/catch that silently discards exceptions (`catch { continue; }`, `catch { return null; }`), establish that the exception is a truly expected, recoverable condition rather than an unexpected error signaling a deeper problem (race conditions, memory corruption, build environment issues). Silently catching exceptions that "shouldn't happen" hides root causes and makes debugging harder. Let unexpected exceptions propagate or fail fast so the real issue gets investigated.
21
22### Thread Safety
23
24- **Use `Volatile` or `Interlocked` for cross-thread field access.** Fields written on one thread and read on another must use `Volatile<T>`, `Volatile.Read/Write`, or `Interlocked`. The `??=` operator is not thread-safe. `Nullable<T>` is not safe for caching (two-field struct tears). Do not use shared mutable arrays without synchronization.
25- **Use `TickCount64` for timeout calculations.** Use `Environment.TickCount64` (long) instead of `Environment.TickCount` (int) to avoid integer overflow.
26
27### Security
28
29- **Guard integer arithmetic against overflow before mutating state.** Guard size computations involving multiplication (e.g., `newCapacity * sizeof(T)`) with checked arithmetic or an explicit bounds check. A `checked` expression is sufficient only when it throws before partial state mutation. When a guard is separated from the arithmetic it protects, add a brief comment connecting them.
30- **Clean sensitive cryptographic data after use.** Always clear key material with `CryptographicOperations.ZeroMemory`. When using `PinAndClear` but copying to another buffer, clear the original too. Use non-short-circuit operators (`|`) in verification code to prevent timing leaks.
31- **Don't proactively send credentials without opt-in.** Never send authentication credentials (especially Basic auth) before receiving a challenge.
32- **Limit `stackalloc` to ~1KB total per method and validate size.** Don't stackalloc based on user-controlled or large input sizes. The total stackalloc budget across the entire method (not just the visible scope) must stay under ~1KB. If the method does a user callback, has unknown call depth, or potential for recursion, reduce the budget further or don't use stackalloc at all. Move stackalloc to just before usage, not before early returns. Use the bounded pattern `(length > Threshold) ? stackalloc[Threshold] : ArrayPool.Rent(length)` to safely cap user input.
33
34### Correctness Patterns
35
36- **Prefer safe code over unsafe micro-optimizations.** Do not introduce `Unsafe.As`, `Unsafe.AsRef`, or raw pointers without demonstrable performance need. Prefer Span-based APIs. If performance is the issue, prefer fixing the JIT. Never convert safe code to unsafe as a side effect of an unrelated functional change.
37- **Use `Unsafe.BitCast` for same-size type punning between blittable types.** Prefer `Unsafe.BitCast<TFrom, TTo>` over `Unsafe.As<TFrom, TTo>` for type punning between unmanaged value types of the same size. For common cases, prefer safe alternatives (e.g., `BitConverter.SingleToInt32Bits` for `float`→`int`).
38- **Handle `SafeHandle.IsInvalid` before `Dispose`.** Check `IsInvalid` (not null) on returned SafeHandles. Get the exception before calling `Dispose`, since Dispose might clear the error state.
39- **Seal classes when `Equals` uses exact type matching.** If a class implements `Equals` with `GetType()` comparison, treat this as a potential bug when the class is unsealed. Sealing is usually the right fix, but not always — evaluate rather than applying it reflexively.
40- **Use `Environment.ProcessPath` and `AppContext.BaseDirectory`.** Use these instead of `Process.GetCurrentProcess().MainModule?.FileName` and `Assembly.Location` for NativeAOT/single-file compatibility.
41- **File name casing must match csproj references exactly.** Linux is case-sensitive. New source files must be listed in the `.csproj` if other files in that folder are explicitly listed.
42
43## Performance & Allocations
44
45### Measurement & Evidence
46
47- **Justify binary size increases with real-world measurements.** Changes that increase binary size require measured wall-clock improvements on real-world apps, not just instruction counts.
48- **Avoid premature optimization with object pools and caches.** Do not introduce global caches or object pools without evidence they are needed. Prefer making the underlying operation faster.
49
50### Allocation Avoidance
51
52- **Avoid closures and allocations in hot paths.** When a lambda captures locals creating a closure, consider using a static delegate with a state parameter (value tuple). Avoid string concatenation; use span-based operations.
53- **Pre-allocate collections when size is known.** Pass capacity to `Dictionary`, `HashSet`, `List` constructors when the expected count is available.
54- **Structs in dictionaries need `IEquatable<T>` and `GetHashCode`.** Without these, the runtime falls back to boxing allocations for equality comparison.
55- **Avoid Pinned Object Heap for non-permanent objects.** POH is never compacted and effectively gen2. Only use for objects surviving as long as the process.
56- **Suppress `ExecutionContext` flow for infrastructure timers.** When allocating `Timer` or similar background infrastructure, suppress EC flow to avoid capturing unrelated `AsyncLocal`s that leak memory.
57
58### Code Structure for Performance
59
60- **Place cheap checks before expensive operations.** Order conditionals so cheapest/most-common checks come first. Move expensive work after early-exit checks.
61- **Allocate resources lazily where possible.** Allocate expensive resources on first use, not during initialization. Avoid forcing type initialization during startup.
62- **Extract throw helpers into `[DoesNotReturn]` methods.** Move throwing logic from error paths into separate static local functions or helper methods to allow the JIT to inline the success path.
63- **Avoid O(n²) patterns in collections and hot paths.** Watch for linear scans inside loops, repeated `RemoveAt` in loops. Use `RemoveAll`, single-pass restructuring, or appropriate data structures.
64- **Cache repeated accessor calls in locals.** Store the result of repeated property/getter calls in a local variable.
65- **Consider scalability, not just throughput.** Evaluate whether data structures, caches, and locking strategies will hold up at high cardinality or under concurrent load. Watch for unbounded collection growth, lock contention that worsens with core count, and O(1) assumptions that break at scale.
66
67### Specific API Choices
68
69- **Use `AppContext.TryGetSwitch` with a static readonly property.** Cache AppContext switches in `static bool Prop { get; } = AppContext.TryGetSwitch(...)` so the JIT can dead-code-eliminate unreachable paths.
70- **Do not cache `typeof` expressions in .NET Core.** `typeof(...)` is JITed into a constant; caching it is a de-optimization. Similarly, don't store `ArrayPool.Shared` in variables—it breaks devirtualization.
71- **Use `CollectionsMarshal` for large value-type dictionary lookups.** Use `GetValueRefOrAddDefault` or `GetValueRefOrNullRef` to avoid copying large structs. Use `ValueListBuilder` on hot paths.
72- **Use `sizeof` consistently.** A pass removed calls to the equivalent `Unsafe` helper; do not reintroduce them. Use `sizeof` rather than `Marshal.SizeOf` for blittable structs; it is more correct and significantly faster when no marshalling is involved.
73- **Use the idiomatic `(uint)index >= (uint)length` bounds check.** The JIT recognizes this pattern and optimizes it. Slice spans before iterating to avoid per-element bounds checks.
74- **Source generators must be properly incremental.** Do not store Roslyn symbols (`ISymbol`, `Compilation`) in incremental pipeline steps. Output must be deterministic with Ordinal-sorted lists.
75- **Use `ValueListBuilder` for dynamic array building in BCL.** Use `ValueListBuilder<T>` (with pooling) or `ArrayBuilder<T>`. Use stackalloc for small sizes, array pool when too large.
76
77## API Design & Contracts
78
79- **Implementation must match the approved API shape.** Deferring portions of an approved API to incremental follow-up PRs is explicitly allowed, as is excluding specific members for technical reasons — unless the exclusion significantly impacts the design.
80- **Use `internal` for new APIs pending API review.** If the API is needed immediately for implementation, mark it `internal` and file a review request separately. This governs code being submitted — an `api-proposal` prototype branch keeps the surface public so ref source generation can extract it.
81- **Parameter names must match between ref and src.** Renaming a public API parameter (including case changes) is a breaking change affecting named arguments and late-bound scenarios.
82- **Align exception types and validation order across platforms.** Validate arguments first (`ArgumentNullException`, then `ArgumentException`), then `PNSE`, then `ObjectDisposedException`, then perform the operation. Throw the same exception types on all platforms.
83- **`Try` APIs should return `false` only for the common expected failure.** Throw for everything else (corruption, permissions, invalid arguments). Try methods must always throw on invalid arguments.
84- **Don't expose mutable options after construction.** If values are captured at construction time, don't expose a mutable options object. Don't reference private field names or internal types in user-facing error messages.
85- **Use `PlatformNotSupportedException` for platform limitations.** When an operation can't complete in the current environment but could on a different platform, throw PNSE. Don't impose artificial limits beyond OS capabilities.
86- **.NET APIs should compensate for platform quirks.** Public APIs should work consistently across platforms. When adding overloads, check F# compatibility for implicit conversion or type inference ambiguities.
87- **Follow the obsoletion process for deprecated APIs.** Pick the next available SYSLIB diagnostic ID, add `[Obsolete]`, and use `[EditorBrowsable(Never)]` with `[OverloadResolutionPriority(-1)]` for overload fixes.
88- **New virtual methods must work with unoverridden derived types.** The default implementation must behave identically to calling the pre-existing equivalent APIs.
89- **Avoid non-CLS-compliant integer types in public APIs.** Preserve `byte`, `int`, or `long` according to the required range; `byte` is valid even though it is unsigned. Use named types instead of `ValueTuple` across file boundaries.
90
91## Code Style & Formatting
92
93- **Use well-named constants instead of magic numbers.** No raw hex or decimal constants without explanation. Don't duplicate magic constants across files.
94- **Use `var` only when the type is apparent from the right-hand side.** "Apparent" means the type is visible as a literal, constructor (`new Foo()`), or explicit cast — not merely "obvious from context." For example, `var x = y.ToString()` is not considered apparent because it's neither a literal nor a constructor. Follow the `.editorconfig` rules for `var` usage. Never use `var` for numeric types.
95- **Use PascalCase for constants; descriptive names for booleans.** All constant locals and fields use PascalCase (except interop constants matching external names). Boolean fields should be positive and descriptive (`_hasCurrent` not `valid`).
96- **Name methods to accurately reflect their behavior.** Update names when behavior changes. `Get*` implies a return value; use `Print*/Display*` for void. `ThrowIf` not `ThrowExceptionIf`.
97- **Prefer early return to reduce nesting.** Use early returns for short/error cases to avoid unnecessary nesting. Put the error case first, success return last.
98- **Avoid `using static` and `#region` in new code.** `using static` is costly when reading code outside IDEs (e.g., GitHub review). `#region` gets out of date quickly.
99- **Place local functions at method end, fields first in types.** Local functions go at the end of the containing method. Fields are the first members declared in a type.
100- **Narrow warning suppression to smallest scope.** Avoid file-wide `#pragma` suppressions. Disable only around the specific line that triggers the warning.
101- **Use pattern matching and `is`/`or`/`and` patterns.** Prefer `is` patterns and C# pattern matching over manual type checks and comparisons. Use named parameters for boolean arguments.
102- **Do not initialize managed fields to default values (CA1805).** The CLR zero-initializes all fields in managed code. Explicit `= false`, `= 0`, `= null` is redundant. (This does not apply to native C/C++ code, where fields and locals must be explicitly initialized.)
103- **Sealed classes do not need the full Dispose pattern.** A simple `Dispose()` is sufficient since no derived class can introduce a finalizer.
104
105## Platform & Cross-Platform
106
107- **Use `BinaryPrimitives` for endianness-safe reads.** Use `ReadInt32LittleEndian`/`BigEndian` rather than pointer casts. Separate endianness-specific reads from target-endianness reads.
108- **Use cross-platform vector APIs over ISA-specific intrinsics.** Prefer `Vector128/256/512.IsHardwareAccelerated` and cross-platform APIs (`.Shuffle`, `.Min`) over `Avx512BW`, `SSE2`. Use the bit manipulation APIs exposed directly on numeric types (e.g., `int.PopCount`, `long.LeadingZeroCount`) rather than `BitOperations` for portable bit manipulation.
109
dotnet/runtime · .github/copilot-instructions.md
@@ +1 @@
1**If at any time, the user directs you explicitly to override any of these instructions, the user's directive overrides said instructions.**
2
3**Don't claim more than you verified.** Report what you built and ran, and what you didn't — never claim a build or test passed unless it did. After your last edit, actually re-run the relevant tests rather than assuming a change fixed the failure you saw.
4
5Scale the effort to the risk. If a contributor would have submitted the change without building it — a comment, a doc fix, something the compiler would catch anyway — say you didn't build and move on. Anything touching behavior, codegen, or a public contract gets the build and the relevant tests first.
6
7Use the `code-review` skill when reviewing pull requests, and — when running under CCA — on your own changes before completing, addressing anything it flags as an error or warning. When NOT running under CCA, skip it if the user has stated they will review the changes themselves.
8
9When starting work in an unfamiliar directory, search for `README.md` files in it and its parents up to the repository root. Read any you find — they contain conventions, patterns, and architectural context relevant to your work.
10
11If the changes are intended to improve performance, or if they could negatively impact performance, use the `performance-benchmark` skill to validate the impact before completing.
12
13When writing or reviewing SIMD / hardware-intrinsics code (anything using `Vector128`/`Vector256`/`Vector512`, `Vector<T>`, or the platform intrinsics in `System.Runtime.Intrinsics.*`), use the `vectorization` skill.
14
15You MUST follow all code-formatting and naming conventions defined in [`.editorconfig`](/.editorconfig).
16
17In addition to the rules enforced by `.editorconfig`, when writing C# you SHOULD:
18
19- Prefer file-scoped namespace declarations and single-line using directives.
20- Ensure that the final return statement of a method is on its own line.
21- Use pattern matching and switch expressions wherever possible.
22- Use `nameof` instead of string literals when referring to member names.
23- Always use `is null` or `is not null` instead of `== null` or `!= null`.
24- Trust the C# null annotations and don't add null checks when the type system says a value cannot be null.
25- Prefer `?.` if applicable (e.g. `scope?.Dispose()`).
26- Use `ObjectDisposedException.ThrowIf` where applicable.
27- If you add new code files, ensure they are listed in the csproj file (if other files in that folder are listed there) so they build.
28- When adding XML documentation to APIs, follow the guidelines at [`docs.prompt.md`](/.github/prompts/docs.prompt.md).
29
30When writing or modifying tests, you SHOULD:
31
32- Strongly prefer to add new unit tests to existing test code files rather than creating new code files.
33- When adding new test files, examine the directory structure of sibling tests first. Some test directories use flat files (e.g., `GCEvents.cs` alongside `GCEvents.csproj`) while others use per-test subdirectories. Match the existing convention.
34- Avoid adding a regression comment citing a GitHub issue or PR number unless explicitly asked to include such information.
35- Prefer using `[Theory]` with multiple data sources (like `[InlineData]` or `[MemberData]`) over multiple duplicative `[Fact]` methods. Fewer test methods that validate more inputs are better than many similar test methods.
36- When running tests, if possible use filters and check test run counts, or look at test logs, to ensure they actually ran.
37- Do not finish work with any tests commented out or disabled that were not previously commented out or disabled.
38- Do not emit "Act", "Arrange" or "Assert" comments.
39
40For markdown (`.md`) files, ensure there is no trailing whitespace at the end of any line.
41
42## Pull Requests
43
44- **One concern per PR.** Split large or mixed changes. Do large refactorings and mechanical renames in their own PR, separate from logic changes.
45- **New public API requires an approved proposal before submission** — PRs adding unapproved API will be closed. Use the `api-proposal` skill; until approval lands the API stays `internal` in any submitted PR. A proposal's prototype branch is exempt and keeps its surface public — it's evidence, not a submission.
46- **Core component changes should start with an issue.** Changes to the host, VM, or JIT need a GitHub issue describing the problem and motivation first.
47- **Put the measurements in the description** for performance changes — BenchmarkDotNet results, or codegen and instruction-count evidence for low-level work.
48- **Behavioral changes need breaking-change documentation**, even prerelease-to-prerelease. Use the `breaking-change-doc` skill.
49- **Merge to main first, then `/backport`.** Servicing backports are limited to security bugs, regressions, and reliability issues, and should be small targeted fixes rather than refactorings.
50- **A push to an open PR re-runs its CI matrix** — dozens of jobs, over a hundred for broad changes. For anything non-trivial, validate locally rather than using CI to find out whether it builds, and batch fixes into one push. Branches with no PR trigger nothing, as do changes confined to `**.md`, `docs/*`, or `.github/*`.
51- **Treat review feedback as a sample, not a list.** A reviewer flags examples of a problem, not every instance. Grep for the rest of the class and fix it in the same push, and answer a whole round of comments at once rather than pushing per comment.
52
53When NOT running under CCA, for commits and pushes:
54
55- Never squash and force push unless explicitly instructed. Always push incremental commits on top of previous PR changes.
56- Never push to an active PR without being explicitly asked, even in autopilot/yolo mode. Always wait for explicit instruction to push.
57- Never chain commit and push in the same command. Always commit first, report what was committed, then wait for an explicit push instruction. This creates a mandatory decision point.
58- Prefer creating a new commit rather than amending an existing one. Exceptions: (1) explicitly asked to amend, or (2) the existing commit is obviously broken with something minor (e.g., typo or comment fix) and hasn't been pushed yet.
59- **Before posting to GitHub (PRs, issues, comments):** Include the AI-generated content disclosure (see below).
60
61## AI-Generated Content Disclosure
62
63When posting to GitHub under a user's credentials — PR descriptions, issue bodies, comments, review comments, or any other public-facing action — you **MUST** add a concise, visible note (e.g. a `> [!NOTE]` alert) at the bottom of the content indicating it was AI/Copilot-generated. Skip it only when posting from a recognized bot or Copilot app account (e.g. `github-actions[bot]`, `copilot`), where the AI origin is already apparent from the account identity, or when the user explicitly asks you to omit it.
64
65---
66
67## Tool Use
68
69Issue independent tool calls together in one response rather than one at a time. Every round trip re-sends the whole conversation as cached input — measured at roughly half the cost of a call before it does any work — so fewer, wider steps beat many narrow ones.
70
71Redirect long-running commands to a log and poll a bounded view — a tail, a grep for errors, or a status sentinel. Re-reading a running command's output re-sends it from the start every time, so repeatedly checking a long build costs far more than the check is worth. Check the outcome, not the process.
72
73```bash
74<cmd> > out.log 2>&1; echo "exit=$?" > out.status # bash
75<cmd> *> out.log; "exit=$LASTEXITCODE" | Out-File out.status # PowerShell -- $? is a [bool] here
76```
77
78Fetch narrowly: `gh run view --log-failed` over `--log`, `--json`/`--jq` to project only the fields needed, `git diff --stat` before the full diff. Quiet what doesn't detect a non-TTY: `curl -sS`, `--quiet` on `git clone`/`fetch`/`checkout`. MSBuild and `dotnet` already detect it — no flags needed.
79
80## Building & Testing
81
82**Before running any build or test command, use the `build-and-test` skill** — don't guess the commands. Under CCA, invoke it **before making any code changes**; a missing or incorrect baseline build costs 20-40 minutes to recover from.
83
@@ −1 +1 @@
1−---
2−applyTo: "**/*.cs"
3−---
1+**If at any time, the user directs you explicitly to override any of these instructions, the user's directive overrides said instructions.**
42
5−# C# (managed code)
3+**Don't claim more than you verified.** Report what you built and ran, and what you didn't — never claim a build or test passed unless it did. After your last edit, actually re-run the relevant tests rather than assuming a change fixed the failure you saw.
64
7−Conventions for C# changes across `src/`. Also apply `conventions` (all changes), `tests` (test
8−files), and any matching area file (`core-runtime`, `jit`, `system-net-*`, `extensions-*`,
9−`compression`, `cdac`). Native runtime code is covered by `native`.
5+Scale the effort to the risk. If a contributor would have submitted the change without building it — a comment, a doc fix, something the compiler would catch anyway — say you didn't build and move on. Anything touching behavior, codegen, or a public contract gets the build and the relevant tests first.
106
11−## Correctness & Safety
7+Use the `code-review` skill when reviewing pull requests, and — when running under CCA — on your own changes before completing, addressing anything it flags as an error or warning. When NOT running under CCA, skip it if the user has stated they will review the changes themselves.
128
13−### Error Handling & Assertions
9+When starting work in an unfamiliar directory, search for `README.md` files in it and its parents up to the repository root. Read any you find — they contain conventions, patterns, and architectural context relevant to your work.
1410
15−- **Use `Debug.Assert` for internal invariants, not exceptions.** For internal-only callers, assert assumptions rather than throwing `ArgumentException`. Prefer `Debug.Assert(value is not null)` over the null-forgiving operator (`!`).
16−- **Use `throw` for reachable error paths, `UnreachableException` for exhaustive switches.** When a code path might be hit at runtime, throw an exception rather than asserting. Use `throw new UnreachableException()` for default cases in exhaustive switches. Use `PlatformNotSupportedException` (not `NotSupportedException`) for platform gaps.
17−- **Include actionable details in exception messages.** Use `nameof` for parameter names. Include the unsupported type or unexpected value. Never throw empty exceptions.
18−- **Initialize output parameters in all code paths.** When a method has `out` parameters or pointer outputs (`bytesWritten`, `numLocals`), ensure they are initialized to a defined value in all error paths.
19−- **Use `ThrowIf` helpers over manual checks.** Use `ArgumentOutOfRangeException.ThrowIfNegative`, `ObjectDisposedException.ThrowIf`, etc. instead of manual if-then-throw patterns.
20−- **Don't swallow exceptions that mask unexpected errors.** Before adding a try/catch that silently discards exceptions (`catch { continue; }`, `catch { return null; }`), establish that the exception is a truly expected, recoverable condition rather than an unexpected error signaling a deeper problem (race conditions, memory corruption, build environment issues). Silently catching exceptions that "shouldn't happen" hides root causes and makes debugging harder. Let unexpected exceptions propagate or fail fast so the real issue gets investigated.
11+If the changes are intended to improve performance, or if they could negatively impact performance, use the `performance-benchmark` skill to validate the impact before completing.
2112
22−### Thread Safety
13+When writing or reviewing SIMD / hardware-intrinsics code (anything using `Vector128`/`Vector256`/`Vector512`, `Vector<T>`, or the platform intrinsics in `System.Runtime.Intrinsics.*`), use the `vectorization` skill.
2314
24−- **Use `Volatile` or `Interlocked` for cross-thread field access.** Fields written on one thread and read on another must use `Volatile<T>`, `Volatile.Read/Write`, or `Interlocked`. The `??=` operator is not thread-safe. `Nullable<T>` is not safe for caching (two-field struct tears). Do not use shared mutable arrays without synchronization.
25−- **Use `TickCount64` for timeout calculations.** Use `Environment.TickCount64` (long) instead of `Environment.TickCount` (int) to avoid integer overflow.
15+You MUST follow all code-formatting and naming conventions defined in [`.editorconfig`](/.editorconfig).
2616
27−### Security
17+In addition to the rules enforced by `.editorconfig`, when writing C# you SHOULD:
2818
29−- **Guard integer arithmetic against overflow before mutating state.** Guard size computations involving multiplication (e.g., `newCapacity * sizeof(T)`) with checked arithmetic or an explicit bounds check. A `checked` expression is sufficient only when it throws before partial state mutation. When a guard is separated from the arithmetic it protects, add a brief comment connecting them.
30−- **Clean sensitive cryptographic data after use.** Always clear key material with `CryptographicOperations.ZeroMemory`. When using `PinAndClear` but copying to another buffer, clear the original too. Use non-short-circuit operators (`|`) in verification code to prevent timing leaks.
31−- **Don't proactively send credentials without opt-in.** Never send authentication credentials (especially Basic auth) before receiving a challenge.
32−- **Limit `stackalloc` to ~1KB total per method and validate size.** Don't stackalloc based on user-controlled or large input sizes. The total stackalloc budget across the entire method (not just the visible scope) must stay under ~1KB. If the method does a user callback, has unknown call depth, or potential for recursion, reduce the budget further or don't use stackalloc at all. Move stackalloc to just before usage, not before early returns. Use the bounded pattern `(length > Threshold) ? stackalloc[Threshold] : ArrayPool.Rent(length)` to safely cap user input.
19+- Prefer file-scoped namespace declarations and single-line using directives.
20+- Ensure that the final return statement of a method is on its own line.
21+- Use pattern matching and switch expressions wherever possible.
22+- Use `nameof` instead of string literals when referring to member names.
23+- Always use `is null` or `is not null` instead of `== null` or `!= null`.
24+- Trust the C# null annotations and don't add null checks when the type system says a value cannot be null.
25+- Prefer `?.` if applicable (e.g. `scope?.Dispose()`).
26+- Use `ObjectDisposedException.ThrowIf` where applicable.
27+- If you add new code files, ensure they are listed in the csproj file (if other files in that folder are listed there) so they build.
28+- When adding XML documentation to APIs, follow the guidelines at [`docs.prompt.md`](/.github/prompts/docs.prompt.md).
3329
34−### Correctness Patterns
30+When writing or modifying tests, you SHOULD:
3531
36−- **Prefer safe code over unsafe micro-optimizations.** Do not introduce `Unsafe.As`, `Unsafe.AsRef`, or raw pointers without demonstrable performance need. Prefer Span-based APIs. If performance is the issue, prefer fixing the JIT. Never convert safe code to unsafe as a side effect of an unrelated functional change.
37−- **Use `Unsafe.BitCast` for same-size type punning between blittable types.** Prefer `Unsafe.BitCast<TFrom, TTo>` over `Unsafe.As<TFrom, TTo>` for type punning between unmanaged value types of the same size. For common cases, prefer safe alternatives (e.g., `BitConverter.SingleToInt32Bits` for `float`→`int`).
38−- **Handle `SafeHandle.IsInvalid` before `Dispose`.** Check `IsInvalid` (not null) on returned SafeHandles. Get the exception before calling `Dispose`, since Dispose might clear the error state.
39−- **Seal classes when `Equals` uses exact type matching.** If a class implements `Equals` with `GetType()` comparison, treat this as a potential bug when the class is unsealed. Sealing is usually the right fix, but not always — evaluate rather than applying it reflexively.
40−- **Use `Environment.ProcessPath` and `AppContext.BaseDirectory`.** Use these instead of `Process.GetCurrentProcess().MainModule?.FileName` and `Assembly.Location` for NativeAOT/single-file compatibility.
41−- **File name casing must match csproj references exactly.** Linux is case-sensitive. New source files must be listed in the `.csproj` if other files in that folder are explicitly listed.
32+- Strongly prefer to add new unit tests to existing test code files rather than creating new code files.
33+- When adding new test files, examine the directory structure of sibling tests first. Some test directories use flat files (e.g., `GCEvents.cs` alongside `GCEvents.csproj`) while others use per-test subdirectories. Match the existing convention.
34+- Avoid adding a regression comment citing a GitHub issue or PR number unless explicitly asked to include such information.
35+- Prefer using `[Theory]` with multiple data sources (like `[InlineData]` or `[MemberData]`) over multiple duplicative `[Fact]` methods. Fewer test methods that validate more inputs are better than many similar test methods.
36+- When running tests, if possible use filters and check test run counts, or look at test logs, to ensure they actually ran.
37+- Do not finish work with any tests commented out or disabled that were not previously commented out or disabled.
38+- Do not emit "Act", "Arrange" or "Assert" comments.
4239
43−## Performance & Allocations
40+For markdown (`.md`) files, ensure there is no trailing whitespace at the end of any line.
4441
45−### Measurement & Evidence
42+## Pull Requests
4643
47−- **Justify binary size increases with real-world measurements.** Changes that increase binary size require measured wall-clock improvements on real-world apps, not just instruction counts.
48−- **Avoid premature optimization with object pools and caches.** Do not introduce global caches or object pools without evidence they are needed. Prefer making the underlying operation faster.
44+- **One concern per PR.** Split large or mixed changes. Do large refactorings and mechanical renames in their own PR, separate from logic changes.
45+- **New public API requires an approved proposal before submission** — PRs adding unapproved API will be closed. Use the `api-proposal` skill; until approval lands the API stays `internal` in any submitted PR. A proposal's prototype branch is exempt and keeps its surface public — it's evidence, not a submission.
46+- **Core component changes should start with an issue.** Changes to the host, VM, or JIT need a GitHub issue describing the problem and motivation first.
47+- **Put the measurements in the description** for performance changes — BenchmarkDotNet results, or codegen and instruction-count evidence for low-level work.
48+- **Behavioral changes need breaking-change documentation**, even prerelease-to-prerelease. Use the `breaking-change-doc` skill.
49+- **Merge to main first, then `/backport`.** Servicing backports are limited to security bugs, regressions, and reliability issues, and should be small targeted fixes rather than refactorings.
50+- **A push to an open PR re-runs its CI matrix** — dozens of jobs, over a hundred for broad changes. For anything non-trivial, validate locally rather than using CI to find out whether it builds, and batch fixes into one push. Branches with no PR trigger nothing, as do changes confined to `**.md`, `docs/*`, or `.github/*`.
51+- **Treat review feedback as a sample, not a list.** A reviewer flags examples of a problem, not every instance. Grep for the rest of the class and fix it in the same push, and answer a whole round of comments at once rather than pushing per comment.
4952
50−### Allocation Avoidance
53+When NOT running under CCA, for commits and pushes:
5154
52−- **Avoid closures and allocations in hot paths.** When a lambda captures locals creating a closure, consider using a static delegate with a state parameter (value tuple). Avoid string concatenation; use span-based operations.
53−- **Pre-allocate collections when size is known.** Pass capacity to `Dictionary`, `HashSet`, `List` constructors when the expected count is available.
54−- **Structs in dictionaries need `IEquatable<T>` and `GetHashCode`.** Without these, the runtime falls back to boxing allocations for equality comparison.
55−- **Avoid Pinned Object Heap for non-permanent objects.** POH is never compacted and effectively gen2. Only use for objects surviving as long as the process.
56−- **Suppress `ExecutionContext` flow for infrastructure timers.** When allocating `Timer` or similar background infrastructure, suppress EC flow to avoid capturing unrelated `AsyncLocal`s that leak memory.
55+- Never squash and force push unless explicitly instructed. Always push incremental commits on top of previous PR changes.
56+- Never push to an active PR without being explicitly asked, even in autopilot/yolo mode. Always wait for explicit instruction to push.
57+- Never chain commit and push in the same command. Always commit first, report what was committed, then wait for an explicit push instruction. This creates a mandatory decision point.
58+- Prefer creating a new commit rather than amending an existing one. Exceptions: (1) explicitly asked to amend, or (2) the existing commit is obviously broken with something minor (e.g., typo or comment fix) and hasn't been pushed yet.
59+- **Before posting to GitHub (PRs, issues, comments):** Include the AI-generated content disclosure (see below).
5760
58−### Code Structure for Performance
61+## AI-Generated Content Disclosure
5962
60−- **Place cheap checks before expensive operations.** Order conditionals so cheapest/most-common checks come first. Move expensive work after early-exit checks.
61−- **Allocate resources lazily where possible.** Allocate expensive resources on first use, not during initialization. Avoid forcing type initialization during startup.
62−- **Extract throw helpers into `[DoesNotReturn]` methods.** Move throwing logic from error paths into separate static local functions or helper methods to allow the JIT to inline the success path.
63−- **Avoid O(n²) patterns in collections and hot paths.** Watch for linear scans inside loops, repeated `RemoveAt` in loops. Use `RemoveAll`, single-pass restructuring, or appropriate data structures.
64−- **Cache repeated accessor calls in locals.** Store the result of repeated property/getter calls in a local variable.
65−- **Consider scalability, not just throughput.** Evaluate whether data structures, caches, and locking strategies will hold up at high cardinality or under concurrent load. Watch for unbounded collection growth, lock contention that worsens with core count, and O(1) assumptions that break at scale.
63+When posting to GitHub under a user's credentials — PR descriptions, issue bodies, comments, review comments, or any other public-facing action — you **MUST** add a concise, visible note (e.g. a `> [!NOTE]` alert) at the bottom of the content indicating it was AI/Copilot-generated. Skip it only when posting from a recognized bot or Copilot app account (e.g. `github-actions[bot]`, `copilot`), where the AI origin is already apparent from the account identity, or when the user explicitly asks you to omit it.
6664
67−### Specific API Choices
65+---
6866
69−- **Use `AppContext.TryGetSwitch` with a static readonly property.** Cache AppContext switches in `static bool Prop { get; } = AppContext.TryGetSwitch(...)` so the JIT can dead-code-eliminate unreachable paths.
70−- **Do not cache `typeof` expressions in .NET Core.** `typeof(...)` is JITed into a constant; caching it is a de-optimization. Similarly, don't store `ArrayPool.Shared` in variables—it breaks devirtualization.
71−- **Use `CollectionsMarshal` for large value-type dictionary lookups.** Use `GetValueRefOrAddDefault` or `GetValueRefOrNullRef` to avoid copying large structs. Use `ValueListBuilder` on hot paths.
72−- **Use `sizeof` consistently.** A pass removed calls to the equivalent `Unsafe` helper; do not reintroduce them. Use `sizeof` rather than `Marshal.SizeOf` for blittable structs; it is more correct and significantly faster when no marshalling is involved.
73−- **Use the idiomatic `(uint)index >= (uint)length` bounds check.** The JIT recognizes this pattern and optimizes it. Slice spans before iterating to avoid per-element bounds checks.
74−- **Source generators must be properly incremental.** Do not store Roslyn symbols (`ISymbol`, `Compilation`) in incremental pipeline steps. Output must be deterministic with Ordinal-sorted lists.
75−- **Use `ValueListBuilder` for dynamic array building in BCL.** Use `ValueListBuilder<T>` (with pooling) or `ArrayBuilder<T>`. Use stackalloc for small sizes, array pool when too large.
67+## Tool Use
7668
77−## API Design & Contracts
69+Issue independent tool calls together in one response rather than one at a time. Every round trip re-sends the whole conversation as cached input — measured at roughly half the cost of a call before it does any work — so fewer, wider steps beat many narrow ones.
7870
79−- **Implementation must match the approved API shape.** Deferring portions of an approved API to incremental follow-up PRs is explicitly allowed, as is excluding specific members for technical reasons — unless the exclusion significantly impacts the design.
80−- **Use `internal` for new APIs pending API review.** If the API is needed immediately for implementation, mark it `internal` and file a review request separately. This governs code being submitted — an `api-proposal` prototype branch keeps the surface public so ref source generation can extract it.
81−- **Parameter names must match between ref and src.** Renaming a public API parameter (including case changes) is a breaking change affecting named arguments and late-bound scenarios.
82−- **Align exception types and validation order across platforms.** Validate arguments first (`ArgumentNullException`, then `ArgumentException`), then `PNSE`, then `ObjectDisposedException`, then perform the operation. Throw the same exception types on all platforms.
83−- **`Try` APIs should return `false` only for the common expected failure.** Throw for everything else (corruption, permissions, invalid arguments). Try methods must always throw on invalid arguments.
84−- **Don't expose mutable options after construction.** If values are captured at construction time, don't expose a mutable options object. Don't reference private field names or internal types in user-facing error messages.
85−- **Use `PlatformNotSupportedException` for platform limitations.** When an operation can't complete in the current environment but could on a different platform, throw PNSE. Don't impose artificial limits beyond OS capabilities.
86−- **.NET APIs should compensate for platform quirks.** Public APIs should work consistently across platforms. When adding overloads, check F# compatibility for implicit conversion or type inference ambiguities.
87−- **Follow the obsoletion process for deprecated APIs.** Pick the next available SYSLIB diagnostic ID, add `[Obsolete]`, and use `[EditorBrowsable(Never)]` with `[OverloadResolutionPriority(-1)]` for overload fixes.
88−- **New virtual methods must work with unoverridden derived types.** The default implementation must behave identically to calling the pre-existing equivalent APIs.
89−- **Avoid non-CLS-compliant integer types in public APIs.** Preserve `byte`, `int`, or `long` according to the required range; `byte` is valid even though it is unsigned. Use named types instead of `ValueTuple` across file boundaries.
71+Redirect long-running commands to a log and poll a bounded view — a tail, a grep for errors, or a status sentinel. Re-reading a running command's output re-sends it from the start every time, so repeatedly checking a long build costs far more than the check is worth. Check the outcome, not the process.
9072
91−## Code Style & Formatting
73+```bash
74+<cmd> > out.log 2>&1; echo "exit=$?" > out.status # bash
75+<cmd> *> out.log; "exit=$LASTEXITCODE" | Out-File out.status # PowerShell -- $? is a [bool] here
76+```
9277
93−- **Use well-named constants instead of magic numbers.** No raw hex or decimal constants without explanation. Don't duplicate magic constants across files.
94−- **Use `var` only when the type is apparent from the right-hand side.** "Apparent" means the type is visible as a literal, constructor (`new Foo()`), or explicit cast — not merely "obvious from context." For example, `var x = y.ToString()` is not considered apparent because it's neither a literal nor a constructor. Follow the `.editorconfig` rules for `var` usage. Never use `var` for numeric types.
95−- **Use PascalCase for constants; descriptive names for booleans.** All constant locals and fields use PascalCase (except interop constants matching external names). Boolean fields should be positive and descriptive (`_hasCurrent` not `valid`).
96−- **Name methods to accurately reflect their behavior.** Update names when behavior changes. `Get*` implies a return value; use `Print*/Display*` for void. `ThrowIf` not `ThrowExceptionIf`.
97−- **Prefer early return to reduce nesting.** Use early returns for short/error cases to avoid unnecessary nesting. Put the error case first, success return last.
98−- **Avoid `using static` and `#region` in new code.** `using static` is costly when reading code outside IDEs (e.g., GitHub review). `#region` gets out of date quickly.
99−- **Place local functions at method end, fields first in types.** Local functions go at the end of the containing method. Fields are the first members declared in a type.
100−- **Narrow warning suppression to smallest scope.** Avoid file-wide `#pragma` suppressions. Disable only around the specific line that triggers the warning.
101−- **Use pattern matching and `is`/`or`/`and` patterns.** Prefer `is` patterns and C# pattern matching over manual type checks and comparisons. Use named parameters for boolean arguments.
102−- **Do not initialize managed fields to default values (CA1805).** The CLR zero-initializes all fields in managed code. Explicit `= false`, `= 0`, `= null` is redundant. (This does not apply to native C/C++ code, where fields and locals must be explicitly initialized.)
103−- **Sealed classes do not need the full Dispose pattern.** A simple `Dispose()` is sufficient since no derived class can introduce a finalizer.
78+Fetch narrowly: `gh run view --log-failed` over `--log`, `--json`/`--jq` to project only the fields needed, `git diff --stat` before the full diff. Quiet what doesn't detect a non-TTY: `curl -sS`, `--quiet` on `git clone`/`fetch`/`checkout`. MSBuild and `dotnet` already detect it — no flags needed.
10479
105−## Platform & Cross-Platform
80+## Building & Testing
10681
107−- **Use `BinaryPrimitives` for endianness-safe reads.** Use `ReadInt32LittleEndian`/`BigEndian` rather than pointer casts. Separate endianness-specific reads from target-endianness reads.
108−- **Use cross-platform vector APIs over ISA-specific intrinsics.** Prefer `Vector128/256/512.IsHardwareAccelerated` and cross-platform APIs (`.Shuffle`, `.Min`) over `Avx512BW`, `SSE2`. Use the bit manipulation APIs exposed directly on numeric types (e.g., `int.PopCount`, `long.LeadingZeroCount`) rather than `BitOperations` for portable bit manipulation.
82+**Before running any build or test command, use the `build-and-test` skill** — don't guess the commands. Under CCA, invoke it **before making any code changes**; a missing or incorrect baseline build costs 20-40 minutes to recover from.
10983
