feat(skills): add coding-dev.md and per-language rules under code-languages/
Generic coding rules and preferences distilled from existing agent rule files, project AGENTS.md/.rules, and saved memories: - strictness maximal; suppressions must be reported to the user - never filter build/lint/test output through grep/tail/head - reuse > fork > self-implement; generic code becomes its own package - 1000-line file / 100-line function limits, split by concern - regression test every fixed bug; never test against real user data - events over polling; scope discipline; honest reporting Per-language: rust, js-typescript, bash, python, go, csharp-dotnet, c-cpp. Each extends coding-dev.md rather than repeating it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ba95f171b2
commit
57968904bf
9 files changed
+1499
-1
No files matched your search
@@ -0,0 +1,151 @@
|
||||
---
|
||||
name: csharp-dotnet
|
||||
description: >-
|
||||
Use this skill when writing, building, or releasing C# / .NET code — including nullable
|
||||
reference types, warnings-as-errors, analyzer configuration, async/await rules, trimming
|
||||
and single-file publishing, and multi-generation SDK compatibility shims.
|
||||
---
|
||||
|
||||
# C# / .NET — Rules & Preferences
|
||||
|
||||
Extends [`../coding-dev.md`](../coding-dev.md). Everything there applies; this adds .NET specifics.
|
||||
|
||||
---
|
||||
|
||||
## 1. Project Settings — Strict By Default
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
<AnalysisLevel>latest-all</AnalysisLevel>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
Put these in a `Directory.Build.props` at the repository root so every project inherits them
|
||||
and none can quietly drift.
|
||||
|
||||
**Every build carries `-warnaserror`:**
|
||||
|
||||
```bash
|
||||
dotnet build MySolution.sln -warnaserror
|
||||
```
|
||||
|
||||
- **Nullable warnings are real bugs.** Never silence one with `!` (null-forgiving) — narrow
|
||||
the type or fix the contract. `!` is an assertion, and an assertion you cannot prove is a
|
||||
future `NullReferenceException`.
|
||||
- Never blanket-disable an analyzer. If a rule is genuinely wrong for the codebase, configure
|
||||
it once in `.editorconfig` with a comment.
|
||||
|
||||
---
|
||||
|
||||
## 2. Async
|
||||
|
||||
- **`async`/`await` throughout; never `.Result` or `.Wait()`** — both deadlock in any context
|
||||
with a synchronization context, and turn an exception into an `AggregateException`.
|
||||
- `async Task`, never `async void`, except for genuine event handlers.
|
||||
- `ConfigureAwait(false)` in library code; not needed in app code on modern hosts.
|
||||
- Accept a `CancellationToken` on every async public method and actually honor it.
|
||||
- `IAsyncEnumerable<T>` for streaming rather than materializing a whole collection.
|
||||
- **Events over polling** — subscribe to the framework's event/observable API; don't run a
|
||||
timer loop. (Global rule; it applies fully here.)
|
||||
|
||||
---
|
||||
|
||||
## 3. Errors, Disposal & Logging
|
||||
|
||||
- Specific exception types; never `catch (Exception)` without a reason and a log.
|
||||
- **Never an empty catch block.**
|
||||
- `using`/`await using` declarations for everything `IDisposable`/`IAsyncDisposable`.
|
||||
Disposal is not optional for streams, HTTP handlers, DB contexts, or native handles.
|
||||
- **One static `HttpClient` (or `IHttpClientFactory`)** — a per-request `HttpClient` exhausts
|
||||
sockets under load.
|
||||
- Structured logging (Serilog or `ILogger<T>`) with message templates, not string interpolation:
|
||||
`logger.LogInformation("Loaded {Count} items", count)` — the template is what makes the log
|
||||
queryable.
|
||||
- **Never log secrets.**
|
||||
|
||||
---
|
||||
|
||||
## 4. Style
|
||||
|
||||
- File-scoped namespaces, `var` for obvious types, target-typed `new()`.
|
||||
- `record` for immutable value types; `readonly struct` for small value types.
|
||||
- Pattern matching and switch expressions over `if`/`else` ladders.
|
||||
- `IReadOnlyList<T>` / `IReadOnlyDictionary<K,V>` in public signatures returning collections.
|
||||
- `internal` by default; `public` only for genuine API surface.
|
||||
- File and function size limits from the general rules apply.
|
||||
- `dotnet format` before committing.
|
||||
|
||||
---
|
||||
|
||||
## 5. Publishing — Trimming & Single File
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **The trimmer only runs on a Release/trimmed/single-file publish.** A Debug build cannot
|
||||
> reproduce the trimmer dropping a type that only reflection reaches. If your release pipeline
|
||||
> ships trimmed binaries, the publish step is the **only** one that exercises the trimmer —
|
||||
> so it must run before release, not after.
|
||||
|
||||
- Annotate reflection-reached types with `[DynamicallyAccessedMembers]` or a
|
||||
`TrimmerRootDescriptor`, and **smoke-test the published binary**, not just the build.
|
||||
- Enable `<IsTrimmable>` per library deliberately; blanket trimming of a plugin host breaks
|
||||
plugin loading.
|
||||
- **A release is a fixed, complete set of assets.** Define what that set is, and have the
|
||||
release step verify it is complete rather than trusting whatever happens to be in the output
|
||||
directory. A packaging tool that silently skips a step when a dependency is missing will
|
||||
otherwise ship a release with a missing platform.
|
||||
|
||||
---
|
||||
|
||||
## 6. Multi-Generation SDK Compatibility
|
||||
|
||||
When targeting several generations of a host SDK whose API changed shape (a class becoming an
|
||||
interface, a type being renamed):
|
||||
|
||||
- **All compatibility code lives in dedicated shim files** — e.g. `GlobalUsings.cs` and
|
||||
`<Host>SdkShims.cs`. Never scatter `#if` directives through feature code.
|
||||
- Select the target with an MSBuild property so the build is explicit about which generation
|
||||
it produced:
|
||||
```bash
|
||||
dotnet build MyModules.csproj -c Release -p:HostTarget=stable
|
||||
dotnet build MyModules.csproj -c Release -p:HostTarget=beta
|
||||
```
|
||||
- Document the differences between generations in the project's agent/contributor file —
|
||||
which types changed, and which direction each shim adapts.
|
||||
- Keep a local package feed for SDK versions not published to the public registry, and script
|
||||
the packing step rather than doing it by hand.
|
||||
|
||||
---
|
||||
|
||||
## 7. Testing
|
||||
|
||||
- xUnit (or the project's existing framework); `FluentAssertions` for readable assertions.
|
||||
- **Regression test every fixed bug.**
|
||||
- Inject abstractions for filesystem, clock, and network so they can be faked — do not reach
|
||||
for a static.
|
||||
- **Never test mutations against real user profiles, real config directories, or live
|
||||
services.** Fixtures and injected backends only.
|
||||
- Test the **published** artifact for anything involving trimming, single-file packing, or
|
||||
native dependencies — the assembly that passed unit tests is not the one you shipped.
|
||||
|
||||
---
|
||||
|
||||
## 8. Toolchain Notes
|
||||
|
||||
- When the SDK is not installed on the host (immutable OS, mismatched glibc), build inside the
|
||||
project's designated container. Entering one resets the working directory — chain `cd` in the
|
||||
same command string.
|
||||
- Prefer the project's build script over hand-typed `dotnet` calls; it carries `-warnaserror`,
|
||||
the correct action ordering, and the asset completeness checks.
|
||||
- **Never stop, deploy to, or restart an application while the user has it running**, unless
|
||||
they have said to.
|
||||
|
||||
---
|
||||
|
||||
## 9. Related
|
||||
- [`../coding-dev.md`](../coding-dev.md) — the general rules this extends.
|
||||
- [`bash.md`](./bash.md) — for the release pipeline scripts around a .NET build.
|
||||
Reference in new issue
Block a user