@pratikpsl/agent-skills 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +92 -0
  3. package/bin/agent-skills.js +7 -0
  4. package/package.json +37 -0
  5. package/src/__tests__/copySkills.test.js +161 -0
  6. package/src/__tests__/list.test.js +49 -0
  7. package/src/__tests__/manifest.test.js +72 -0
  8. package/src/commands/add.js +89 -0
  9. package/src/commands/dotnet-setup.js +67 -0
  10. package/src/commands/init.js +42 -0
  11. package/src/commands/list.js +41 -0
  12. package/src/index.js +33 -0
  13. package/src/lib/copySkills.js +84 -0
  14. package/src/lib/manifest.js +117 -0
  15. package/src/lib/resolvePack.js +44 -0
  16. package/src/templates/dotnet/AgentSkills/OPERATING.md +85 -0
  17. package/src/templates/dotnet/AgentSkills/README.md +64 -0
  18. package/src/templates/dotnet/AgentSkills/agents/README.md +16 -0
  19. package/src/templates/dotnet/AgentSkills/agents/architect.agent.md +59 -0
  20. package/src/templates/dotnet/AgentSkills/agents/developer.agent.md +88 -0
  21. package/src/templates/dotnet/AgentSkills/entry-points/AGENTS.md +16 -0
  22. package/src/templates/dotnet/AgentSkills/entry-points/CLAUDE.md +16 -0
  23. package/src/templates/dotnet/AgentSkills/entry-points/copilot-instructions.md +16 -0
  24. package/src/templates/dotnet/AgentSkills/entry-points/cursor-instructions.md +16 -0
  25. package/src/templates/dotnet/AgentSkills/memory/index.md +22 -0
  26. package/src/templates/dotnet/AgentSkills/memory/lessons/api.md +3 -0
  27. package/src/templates/dotnet/AgentSkills/memory/lessons/auth.md +3 -0
  28. package/src/templates/dotnet/AgentSkills/memory/lessons/csharp.md +3 -0
  29. package/src/templates/dotnet/AgentSkills/memory/lessons/db.md +3 -0
  30. package/src/templates/dotnet/AgentSkills/memory/lessons/design.md +3 -0
  31. package/src/templates/dotnet/AgentSkills/memory/lessons/infra.md +7 -0
  32. package/src/templates/dotnet/AgentSkills/memory/lessons/mcp.md +3 -0
  33. package/src/templates/dotnet/AgentSkills/memory/lessons/testing.md +3 -0
  34. package/src/templates/dotnet/AgentSkills/memory/schema.md +26 -0
  35. package/src/templates/dotnet/AgentSkills/skills/INDEX.md +21 -0
  36. package/src/templates/dotnet/AgentSkills/skills/README.md +14 -0
  37. package/src/templates/dotnet/AgentSkills/skills/code-standards/SKILL.md +122 -0
  38. package/src/templates/dotnet/AgentSkills/skills/core/SKILL.md +83 -0
  39. package/src/templates/dotnet/AgentSkills/skills/csharp-xunit/SKILL.md +68 -0
  40. package/src/templates/dotnet/AgentSkills/skills/design/SKILL.md +108 -0
  41. package/src/templates/dotnet/AgentSkills/skills/dotnet-api/SKILL.md +303 -0
  42. package/src/templates/dotnet/AgentSkills/skills/dotnet-best-practices/SKILL.md +170 -0
  43. package/src/templates/dotnet/AgentSkills/skills/harness/SKILL.md +62 -0
  44. package/src/templates/dotnet/AgentSkills/skills/mcp_dotnet/SKILL.md +54 -0
  45. package/src/templates/dotnet/manifest.json +86 -0
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: design
3
+ description: >
4
+ Load when designing, architecting, or implementing patterns in C#.
5
+ Covers project folder structure (vertical slice), SOLID, KISS, YAGNI,
6
+ DRY, composition, Singleton, and Factory.
7
+ ---
8
+
9
+ # Design Principles and Patterns
10
+
11
+ ## Project Structure
12
+
13
+ Organise by **feature (vertical slice)**, not by technical layer.
14
+ Each feature folder owns everything needed for its use case: command, handler, DTO, validator, and endpoint.
15
+ This keeps changes local, avoids cross-cutting layers, and scales without requiring global refactors.
16
+
17
+ ```text
18
+ src/
19
+ ├── Features/
20
+ │ ├── Products/
21
+ │ │ ├── CreateProductCommand.cs
22
+ │ │ ├── CreateProductHandler.cs
23
+ │ │ ├── ProductDto.cs
24
+ │ │ ├── ProductValidator.cs
25
+ │ │ └── ProductEndpoints.cs
26
+ │ ├── Orders/
27
+ │ │ ├── CreateOrderCommand.cs
28
+ │ │ ├── CreateOrderHandler.cs
29
+ │ │ ├── OrderDto.cs
30
+ │ │ ├── OrderValidator.cs
31
+ │ │ └── OrderEndpoints.cs
32
+ │ └── ...
33
+ ├── Shared/
34
+ │ ├── Middleware/
35
+ │ └── Utilities/
36
+ └── Program.cs
37
+ ```
38
+
39
+ **Rules:**
40
+ - One folder per feature — never split a feature across `Commands/`, `Queries/`, `Controllers/` top-level layers.
41
+ - When a feature grows, split it into sub-features within the same `Features/<Feature>/` directory before creating a new top-level folder.
42
+ - Shared cross-cutting code (middleware, utilities, base types) lives in `Shared/`, not duplicated per feature.
43
+ - `Program.cs` wires up DI, middleware, and endpoint registration only — no business logic.
44
+
45
+ ## SOLID
46
+
47
+ | | Principle | In Practice |
48
+ |---|---|---|
49
+ | S | Single Responsibility | One class, one reason to change |
50
+ | O | Open / Closed | Open to extension, closed to modification |
51
+ | L | Liskov Substitution | Subtypes must work wherever the base type works |
52
+ | I | Interface Segregation | Small, focused interfaces over large, general ones |
53
+ | D | Dependency Inversion | Depend on abstractions, not concrete implementations |
54
+
55
+ ## KISS
56
+
57
+ Prefer the obvious solution. If a junior engineer cannot understand it in 5 minutes, simplify it.
58
+
59
+ ## YAGNI
60
+
61
+ Do not build something until it is needed. Solve today's requirement, not tomorrow's guess.
62
+
63
+ ```csharp
64
+ // Bad: built "just in case" when only one format exists.
65
+ public interface IExporter { }
66
+ public class ExporterFactory { }
67
+
68
+ // Good: solve what exists now.
69
+ public string ExportToCsv(Report report) { }
70
+ ```
71
+
72
+ ## DRY
73
+
74
+ Keep one source of truth per piece of knowledge: logic, configuration, and data schemas.
75
+
76
+ ## Composition Over Inheritance
77
+
78
+ Use inheritance only for true "is-a" relationships. Prefer interfaces and delegation.
79
+
80
+ ## Pattern: Singleton
81
+
82
+ Use when exactly one instance must coordinate shared state. Avoid when it creates hidden global state.
83
+
84
+ ```csharp
85
+ public sealed class AppConfig
86
+ {
87
+ private static readonly Lazy<AppConfig> InstanceHolder =
88
+ new(() => new AppConfig());
89
+
90
+ public static AppConfig Instance => InstanceHolder.Value;
91
+
92
+ private AppConfig()
93
+ {
94
+ }
95
+ }
96
+ ```
97
+
98
+ ## Pattern: Factory
99
+
100
+ Use when creation is complex, varies by type, or must be decoupled from consumers.
101
+
102
+ ```csharp
103
+ // Bad
104
+ var handler = type == "email" ? new EmailHandler() : new SmsHandler();
105
+
106
+ // Good
107
+ var handler = NotificationFactory.Create(type);
108
+ ```
@@ -0,0 +1,303 @@
1
+ ---
2
+ name: dotnet-api
3
+ description: >
4
+ Load when creating, structuring, or reviewing .NET 10 Web API projects with Swagger/OpenAPI, CORS, compression, auth, versioning, and error handling.
5
+ ---
6
+
7
+ # SKILL: .NET 10 RESTful API — Best Practices
8
+
9
+ ## 1. URL & RESOURCE NAMING
10
+
11
+ - **Nouns only**, plural: `/api/v1/articles`, `/api/v1/users`
12
+ - HTTP verb = action; path = resource
13
+ - Nest max 2 levels: `GET /articles/123/comments`
14
+ - Beyond 2 levels → return URI in JSON body: `"author": "/users/3"`
15
+
16
+ | ❌ Bad | ✅ Good |
17
+ |---|---|
18
+ | `GET /getArticles` | `GET /articles` |
19
+ | `POST /createUser` | `POST /users` |
20
+
21
+ ---
22
+
23
+ ## 2. HTTP METHODS
24
+
25
+ | Method | Use | Idempotent |
26
+ |---|---|---|
27
+ | GET | Retrieve | ✅ |
28
+ | POST | Create | ❌ |
29
+ | PUT | Full replace | ✅ |
30
+ | PATCH | Partial update | ✅ |
31
+ | DELETE | Remove | ✅ |
32
+
33
+ ---
34
+
35
+ ## 3. RESPONSE FORMAT & HEADERS
36
+
37
+ - Always return `application/json`
38
+ - Use `camelCase` for JSON keys (default in .NET)
39
+ - No outer wrappers — return resource directly
40
+
41
+ ```csharp
42
+ builder.Services.AddControllers()
43
+ .AddJsonOptions(o => o.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase);
44
+ ```
45
+
46
+ ---
47
+
48
+ ## 4. HTTP STATUS CODES
49
+
50
+ | Code | When |
51
+ |---|---|
52
+ | 200 | Success (GET, PUT, PATCH) |
53
+ | 201 | Created (POST) — include `Location` header |
54
+ | 204 | No content (DELETE) |
55
+ | 400 | Bad request / validation failed |
56
+ | 401 | Not authenticated |
57
+ | 403 | Authenticated but forbidden |
58
+ | 404 | Resource not found |
59
+ | 500 | Unhandled server error |
60
+
61
+ ---
62
+
63
+ ## 5. GLOBAL ERROR HANDLING
64
+
65
+ Use `IExceptionHandler` (dotnet 8+) — no stack traces in production.
66
+
67
+ ```csharp
68
+ // GlobalExceptionHandler.cs
69
+ public class GlobalExceptionHandler : IExceptionHandler
70
+ {
71
+ public async ValueTask<bool> TryHandleAsync(HttpContext ctx, Exception ex, CancellationToken ct)
72
+ {
73
+ ctx.Response.StatusCode = StatusCodes.Status500InternalServerError;
74
+ await ctx.Response.WriteAsJsonAsync(new { error = "An unexpected error occurred." }, ct);
75
+ return true;
76
+ }
77
+ }
78
+
79
+ // Program.cs
80
+ builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
81
+ builder.Services.AddProblemDetails();
82
+ app.UseExceptionHandler();
83
+ ```
84
+
85
+ Structured error shape — never raw exceptions:
86
+ ```json
87
+ { "status": 400, "error": "Validation failed", "code": "INVALID_EMAIL" }
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 6. FILTERING, SORTING & PAGINATION
93
+
94
+ Query params only — never in the body for GET.
95
+
96
+ ```
97
+ GET /products?category=electronics&sort=-price&page=2&limit=20
98
+ ```
99
+
100
+ ```csharp
101
+ [HttpGet]
102
+ public IActionResult GetProducts([FromQuery] string? category, [FromQuery] string? sort,
103
+ [FromQuery] int page = 1, [FromQuery] int limit = 20) { ... }
104
+ ```
105
+
106
+ - `sort=price` → ascending, `sort=-price` → descending
107
+ - Always return pagination metadata: `{ total, page, limit, data: [] }`
108
+
109
+ ---
110
+
111
+ ## 7. VERSIONING
112
+
113
+ ```csharp
114
+ // Program.cs
115
+ builder.Services.AddApiVersioning(o => {
116
+ o.DefaultApiVersion = new ApiVersion(1);
117
+ o.AssumeDefaultVersionWhenUnspecified = true;
118
+ o.ReportApiVersions = true;
119
+ }).AddApiExplorer(o => {
120
+ o.GroupNameFormat = "'v'V";
121
+ o.SubstituteApiVersionInUrl = true;
122
+ });
123
+ ```
124
+
125
+ ```csharp
126
+ [ApiVersion(1)]
127
+ [Route("api/v{v:apiVersion}/articles")]
128
+ public class ArticlesController : ControllerBase { }
129
+ ```
130
+
131
+ Package: `Asp.Versioning.Mvc` + `Asp.Versioning.Mvc.ApiExplorer`
132
+
133
+ ---
134
+
135
+ ## 8. SWAGGER / OPENAPI
136
+
137
+ Add to `.csproj`:
138
+ ```xml
139
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
140
+ ```
141
+
142
+ Setup: `AddEndpointsApiExplorer()` + `AddSwaggerGen()` with:
143
+ - `SwaggerDoc` per version
144
+ - `AddSecurityDefinition("Bearer", ...)` + matching `AddSecurityRequirement`
145
+ - `IncludeXmlComments(...)` for XML doc file
146
+
147
+ Controller annotation:
148
+ ```csharp
149
+ /// <summary>Get all articles</summary>
150
+ /// <response code="200">Returns list of articles</response>
151
+ [HttpGet]
152
+ [ProducesResponseType(typeof(List<ArticleDto>), 200)]
153
+ [ProducesResponseType(404)]
154
+ public IActionResult GetAll([FromQuery] int page = 1) { ... }
155
+ ```
156
+
157
+ Expose only in Development:
158
+ ```csharp
159
+ if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); }
160
+ ```
161
+
162
+ ---
163
+
164
+ ## 9. RESPONSE COMPRESSION
165
+
166
+ ```csharp
167
+ builder.Services.AddResponseCompression(o => {
168
+ o.EnableForHttps = true;
169
+ o.Providers.Add<BrotliCompressionProvider>();
170
+ o.Providers.Add<GzipCompressionProvider>();
171
+ });
172
+ builder.Services.Configure<BrotliCompressionProviderOptions>(o => o.Level = CompressionLevel.Fastest);
173
+
174
+ app.UseResponseCompression(); // must be first in pipeline
175
+ ```
176
+
177
+ Package: `Microsoft.AspNetCore.ResponseCompression` (built-in)
178
+
179
+ ---
180
+
181
+ ## 10. CORS (No Wildcard in Production)
182
+
183
+ ```csharp
184
+ builder.Services.AddCors(o => o.AddPolicy("ApiPolicy", p => p
185
+ .WithOrigins("https://myfrontend.com") // ❌ never .AllowAnyOrigin() in prod
186
+ .WithMethods("GET", "POST", "PUT", "DELETE", "PATCH")
187
+ .WithHeaders("Authorization", "Content-Type")
188
+ .AllowCredentials()));
189
+
190
+ app.UseCors("ApiPolicy"); // before UseAuthentication
191
+ ```
192
+
193
+ Dev-only: use a separate named policy with `AllowAnyOrigin()`.
194
+
195
+ ---
196
+
197
+ ## 11. SECURITY
198
+
199
+ ```csharp
200
+ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
201
+ .AddJwtBearer(o => {
202
+ o.TokenValidationParameters = new TokenValidationParameters {
203
+ ValidateIssuer = true, ValidIssuer = config["Jwt:Issuer"],
204
+ ValidateAudience = true, ValidAudience = config["Jwt:Audience"],
205
+ ValidateLifetime = true,
206
+ IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Jwt:Key"]!))
207
+ };
208
+ });
209
+ ```
210
+
211
+ - `app.UseHttpsRedirection()` — mandatory
212
+ - Never expose DB schema in endpoint design
213
+ - Use `[Authorize]` / `[AllowAnonymous]` explicitly on controllers
214
+
215
+ ---
216
+
217
+ ## 12. CACHING
218
+
219
+ Options in order of complexity:
220
+
221
+ | Strategy | Use when |
222
+ |---|---|
223
+ | `[OutputCache(Duration = 60)]` | Single-server, simple GET caching |
224
+ | `IDistributedCache` + Redis | Multi-instance / shared cache |
225
+ | `Cache-Control` header | Client/CDN-side caching |
226
+
227
+ ```csharp
228
+ // Distributed Redis
229
+ builder.Services.AddStackExchangeRedisCache(o => o.Configuration = "localhost:6379");
230
+
231
+ // Client hint
232
+ Response.Headers.CacheControl = "public, max-age=60";
233
+ ```
234
+
235
+ Register `AddOutputCache()` + `app.UseOutputCache()` for attribute-based caching.
236
+
237
+ ---
238
+
239
+ ## 13. RATE LIMITING (dotnet 7+ built-in)
240
+
241
+ ```csharp
242
+ builder.Services.AddRateLimiter(o => o.AddFixedWindowLimiter("fixed", opt => {
243
+ opt.PermitLimit = 100;
244
+ opt.Window = TimeSpan.FromMinutes(1);
245
+ opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
246
+ opt.QueueLimit = 5;
247
+ }));
248
+
249
+ app.UseRateLimiter();
250
+
251
+ [HttpGet, EnableRateLimiting("fixed")]
252
+ public IActionResult Get() { ... }
253
+ ```
254
+
255
+ ---
256
+
257
+ ## 14. INPUT VALIDATION
258
+
259
+ ```csharp
260
+ builder.Services.AddControllers()
261
+ .ConfigureApiBehaviorOptions(o => o.InvalidModelStateResponseFactory = ctx =>
262
+ new BadRequestObjectResult(new {
263
+ status = 400,
264
+ errors = ctx.ModelState.Values
265
+ .SelectMany(v => v.Errors)
266
+ .Select(e => e.ErrorMessage)
267
+ }));
268
+ ```
269
+
270
+ Use `FluentValidation` for complex rules; Data Annotations for simple constraints.
271
+
272
+ ---
273
+
274
+ ## 15. PIPELINE ORDER (Critical)
275
+
276
+ ```csharp
277
+ app.UseResponseCompression();
278
+ app.UseHttpsRedirection();
279
+ app.UseCors("ApiPolicy");
280
+ app.UseRateLimiter();
281
+ app.UseAuthentication();
282
+ app.UseAuthorization();
283
+ app.UseOutputCache();
284
+ app.UseExceptionHandler();
285
+ app.MapControllers();
286
+ ```
287
+
288
+ ---
289
+
290
+ ## QUICK CHECKLIST
291
+
292
+ - [ ] Routes: plural nouns, no verbs, max 2 nesting levels
293
+ - [ ] `201 Created` returns `Location` header; `204` for DELETE
294
+ - [ ] `IExceptionHandler` registered — structured JSON errors, no stack traces
295
+ - [ ] Collections: filtering + sorting + pagination with metadata envelope
296
+ - [ ] Versioning: `Asp.Versioning.Mvc`, `ReportApiVersions = true`
297
+ - [ ] Swagger: XML docs + `ProducesResponseType` on every action + JWT security scheme
298
+ - [ ] Compression: Brotli + Gzip, `EnableForHttps = true`, first in pipeline
299
+ - [ ] CORS: explicit `WithOrigins` — `AllowAnyOrigin` dev policy only
300
+ - [ ] JWT: all 3 validate flags on (`Issuer`, `Audience`, `Lifetime`)
301
+ - [ ] Rate limiting: `AddFixedWindowLimiter` + `EnableRateLimiting` per controller/action
302
+ - [ ] `InvalidModelStateResponseFactory` returns structured 400 with field errors
303
+ - [ ] DTOs only in responses — no raw EF entities exposed
@@ -0,0 +1,170 @@
1
+ ---
2
+ name: dotnet-best-practices
3
+ description: >
4
+ Load when writing, reviewing, refactoring, or optimizing .NET/C# code.
5
+ Covers project conventions, CQRS, EF Core, async, testing, performance,
6
+ logging, security, and maintainability.
7
+ ---
8
+
9
+ # .NET/C# Best Practices
10
+
11
+ Use this skill to keep .NET/C# changes simple, maintainable, testable, and aligned with this repository.
12
+
13
+ ## Repository Defaults
14
+
15
+ - Follow the target framework and language version declared in `Directory.Build.props`.
16
+ - Current defaults are `net10.0` and `LangVersion` set to `latest`.
17
+ - Use modern C# features only when they improve readability or correctness.
18
+ - Prefer clear, boring code over clever code.
19
+ - Keep changes scoped to the current feature or bug.
20
+
21
+ ## Documentation and Structure
22
+
23
+ - Add XML documentation comments for public APIs when they are part of the external or shared surface.
24
+ - Include meaningful parameter and return descriptions when they add information beyond the name.
25
+ - Organize code by feature/domain when the project already follows that structure.
26
+ - Keep controllers, endpoints, handlers, validators, repositories, and DTOs in predictable folders.
27
+ - Use namespaces that match the project and feature structure.
28
+
29
+ ## CQRS and Architecture
30
+
31
+ - Commands mutate state and should return nothing, an ID, or a small result.
32
+ - Queries read state and must not mutate data.
33
+ - Keep controllers and minimal API endpoints thin; they should validate transport concerns and dispatch through MediatR.
34
+ - Put business rules in domain/application services or entities, not controllers.
35
+ - Use one handler per command or query.
36
+ - Prefer records for commands, queries, and DTOs when immutability is appropriate.
37
+ - Mark classes `sealed` unless inheritance is intentionally supported.
38
+ - Use interfaces for boundaries that need substitution, testing, or multiple implementations.
39
+
40
+ ## Dependency Injection and Services
41
+
42
+ - Use constructor injection or primary constructors for required dependencies.
43
+ - Validate required dependencies when nullable flow does not already prove safety.
44
+ - Register services with the narrowest correct lifetime:
45
+ - `Singleton` for stateless, thread-safe services.
46
+ - `Scoped` for request-bound services and EF Core `DbContext`.
47
+ - `Transient` for lightweight stateless services.
48
+ - Do not resolve services manually from `IServiceProvider` unless there is a clear framework boundary.
49
+ - Avoid hidden global state.
50
+
51
+ ## Async/Await
52
+
53
+ - Use async/await for I/O, database, network, and long-running operations.
54
+ - Do not block async work with `.Result`, `.Wait()`, or `.GetAwaiter().GetResult()`.
55
+ - Prefer async all the way through the call chain.
56
+ - Accept and pass `CancellationToken` on request, handler, EF Core, and HTTP calls.
57
+ - Use `ConfigureAwait(false)` in reusable library code when appropriate; it is usually unnecessary in ASP.NET Core request code.
58
+ - Avoid `async void` except for event handlers.
59
+
60
+ ## EF Core and Database Performance
61
+
62
+ - Avoid N+1 queries. Use projections, `Include`, explicit joins, or separate optimized queries.
63
+ - Use `.AsNoTracking()` for read-only queries.
64
+ - Select only required columns into DTOs instead of loading full entities.
65
+ - Add pagination for list endpoints; avoid returning unbounded result sets.
66
+ - Filter in the database, not in memory.
67
+ - Use indexes for frequent filters, joins, and ordering paths.
68
+ - Prefer `AnyAsync` over `CountAsync` when checking existence.
69
+ - Avoid lazy loading in APIs unless there is a specific measured reason.
70
+ - Use `SplitQuery` only when it avoids cartesian explosion from large includes.
71
+ - Batch writes where possible and call `SaveChangesAsync` once per unit of work.
72
+ - Consider `ExecuteUpdateAsync` and `ExecuteDeleteAsync` for bulk updates/deletes.
73
+ - Consider compiled queries only for measured hot paths.
74
+ - Always parameterize raw SQL if raw SQL is truly needed.
75
+
76
+ ## Memory and Allocation Performance
77
+
78
+ - Avoid unnecessary object creation in hot paths.
79
+ - Use `StringBuilder` for repeated string concatenation in loops or large text generation.
80
+ - Be careful with LINQ in hot paths; simple loops can reduce allocations and improve clarity.
81
+ - Avoid exceptions for normal control flow.
82
+ - Prefer `Array.Empty<T>()` over new empty arrays.
83
+ - Reuse static readonly immutable data when safe.
84
+ - Use pooling, `Span<T>`, `Memory<T>`, or `ValueTask` only when measurement shows a real benefit.
85
+
86
+ ## Caching
87
+
88
+ - Cache frequently used, slow-changing data to reduce database and network load.
89
+ - Use in-memory caching for single-instance or per-node data.
90
+ - Use distributed caching such as Redis for multi-instance deployments or shared cache state.
91
+ - Define clear cache keys, expiration, invalidation, and size limits.
92
+ - Avoid caching sensitive user data unless encryption, isolation, and expiry are correct.
93
+ - Prevent cache stampedes for expensive entries with locking or single-flight behavior.
94
+ - Do not cache data that must be strongly consistent unless the domain explicitly allows staleness.
95
+
96
+ ## API Payload and Response Performance
97
+
98
+ - Return DTOs that contain only the fields the caller needs.
99
+ - Use pagination, filtering, and sorting parameters for collection endpoints.
100
+ - Avoid sending large object graphs.
101
+ - Enable response compression for compressible text responses such as JSON, HTML, CSS, and JavaScript.
102
+ - Do not compress already compressed content such as images, videos, zip files, or PDFs.
103
+ - Use ETags, `Last-Modified`, or cache headers where HTTP caching is safe.
104
+ - Prefer streaming for large downloads instead of buffering the full payload in memory.
105
+
106
+ ## Logging and Observability
107
+
108
+ - Use structured logging with message templates and named properties.
109
+ - Avoid excessive logging in hot paths, especially per-item logs in loops.
110
+ - Do not use string interpolation for expensive log messages unless guarded by `logger.IsEnabled(...)`.
111
+ - Log enough context to diagnose failures without logging secrets or personal data.
112
+ - Use correlation IDs, request IDs, or tracing context across request boundaries.
113
+ - Use metrics/tracing for performance-critical paths instead of relying only on logs.
114
+
115
+ ## Efficient Data Structures
116
+
117
+ - Use `Dictionary<TKey, TValue>` for fast key lookups.
118
+ - Use `HashSet<T>` for uniqueness checks and membership tests.
119
+ - Avoid repeated linear searches over large collections.
120
+ - Use `List<T>` when order matters and append/read operations dominate.
121
+ - Choose immutable or read-only collections when shared state should not change.
122
+
123
+ ## HTTP and External Calls
124
+
125
+ - Use `IHttpClientFactory` for outbound HTTP calls.
126
+ - Set timeouts and pass cancellation tokens.
127
+ - Avoid retry storms; use bounded retries with backoff for transient failures.
128
+ - Do not make external calls inside tight loops when batching is possible.
129
+ - Prefer resilient integration patterns for unreliable dependencies.
130
+
131
+ ## Security
132
+
133
+ - Validate and sanitize external input.
134
+ - Use FluentValidation or existing validation patterns for request validation.
135
+ - Never concatenate user input into SQL, file paths, shell commands, or logs.
136
+ - Do not log secrets, tokens, passwords, connection strings, or sensitive personal data.
137
+ - Use least-privilege configuration for database and external services.
138
+
139
+ ## Testing Standards
140
+
141
+ - Use xUnit for unit tests.
142
+ - Use FluentAssertions where it improves readability.
143
+ - Use Moq or the existing repository mocking style for dependencies.
144
+ - Follow Arrange, Act, Assert.
145
+ - Test success, failure, validation, null/empty input, and cancellation paths when relevant.
146
+ - Keep tests deterministic and independent.
147
+
148
+ ## Performance Workflow
149
+
150
+ - Measure before optimizing unless the issue is obvious and local.
151
+ - Prefer simple fixes before complex optimizations.
152
+ - Use realistic data sizes when validating performance.
153
+ - Consider tools such as logs, metrics, traces, `dotnet-counters`, `dotnet-trace`, BenchmarkDotNet, or database query plans.
154
+ - Document any non-obvious optimization with the measured reason.
155
+ - Do not trade correctness, security, or maintainability for small unmeasured gains.
156
+
157
+ ## Review Checklist
158
+
159
+ - [ ] No avoidable N+1 queries.
160
+ - [ ] Read-only EF Core queries use `.AsNoTracking()`.
161
+ - [ ] Queries project only required columns.
162
+ - [ ] Async code does not block on tasks.
163
+ - [ ] Cancellation tokens flow through I/O boundaries.
164
+ - [ ] No excessive allocations in hot paths.
165
+ - [ ] Caching has clear expiration and invalidation.
166
+ - [ ] Logs are structured and not excessive.
167
+ - [ ] API responses avoid unnecessary payload size.
168
+ - [ ] Compression and HTTP caching are used only where appropriate.
169
+ - [ ] Data structures match access patterns.
170
+ - [ ] Tests cover the changed behavior.
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: harness
3
+ description: >
4
+ Load when changing agent instructions, validation scripts, CI workflows,
5
+ hooks, or repository operational guardrails.
6
+ ---
7
+
8
+ # Harness Engineering
9
+
10
+ Harness engineering is the operational layer around the model:
11
+
12
+ ```text
13
+ Agent = Model + Harness
14
+ ```
15
+
16
+ Use this skill when adding or changing guide rails, validation, recovery, or feedback loops.
17
+
18
+ ## Controls
19
+
20
+ | Control | Purpose | Repo examples |
21
+ |---|---|---|
22
+ | Guides | Feedforward controls that steer work before action | `AGENTS.md`, `AgentSkills/skills/INDEX.md`, `AgentSkills/agents/` |
23
+ | Sensors | Feedback controls that observe output after action | `tools/Harness/validate.ps1`, `.github/workflows/dotnet.yml`, `.editorconfig` |
24
+
25
+ ## Rules
26
+
27
+ - Keep `AgentSkills/` as the canonical source of truth.
28
+ - Tool-specific folders may contain lightweight entry points only.
29
+ - Prefer one shared validation command over duplicated CI, hook, and README commands.
30
+ - Sensors must be deterministic first: restore, build, test, format.
31
+ - Use inferential review only after computational checks pass.
32
+ - Keep harness changes small, readable, and easy to remove.
33
+
34
+ ## Agent and IDE Entry Point Contract
35
+
36
+ All coding agents and AI-enabled IDEs must start from
37
+ `AgentSkills/OPERATING.md`.
38
+
39
+ Tool-specific entry points must be short router files that:
40
+
41
+ - Identify themselves as lightweight entry points.
42
+ - Point to `AgentSkills/OPERATING.md`.
43
+ - Point to `AgentSkills/skills/INDEX.md` for skill routing.
44
+ - Point to `AgentSkills/agents/` for optional role definitions.
45
+ - Avoid duplicating project rules, checklists, memory instructions, or skill content.
46
+
47
+ When a new agent or IDE integration is added, create only the smallest entry
48
+ point required by that tool and route it back to `AgentSkills/`.
49
+
50
+ ## Validation
51
+
52
+ Run the shared sensor before finishing changes:
53
+
54
+ ```powershell
55
+ pwsh ./tools/Harness/validate.ps1
56
+ ```
57
+
58
+ For quick local loops:
59
+
60
+ ```powershell
61
+ pwsh ./tools/Harness/validate.ps1 -Configuration Debug -SkipFormat
62
+ ```
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: mcp_dotnet
3
+ description: >
4
+ Load when building, reviewing, or extending .NET MCP server tools,
5
+ transports, contracts, and IDE/client integration.
6
+ ---
7
+
8
+ # MCP .NET Skill
9
+
10
+ Use this skill for Model Context Protocol work in this repository.
11
+
12
+ ## Project Rules
13
+
14
+ - Keep MCP tools thin; route behavior through the same MediatR commands and queries used by REST endpoints.
15
+ - Do not duplicate business logic in MCP tool methods.
16
+ - Treat MCP tool contracts as public API: use stable names, clear descriptions, explicit input types, and small output DTOs.
17
+ - Pass `CancellationToken` through all tool, mediator, EF Core, and HTTP boundaries.
18
+ - Keep stdout reserved for MCP protocol messages when using stdio transport; send logs to stderr.
19
+ - Validate tool inputs before dispatching commands or queries.
20
+ - Avoid exposing raw entities, stack traces, connection strings, secrets, or internal schema details.
21
+ - Add or update tests for tool behavior and contract mapping when MCP behavior changes.
22
+
23
+ ## Tool Design Checklist
24
+
25
+ - [ ] Tool name is action-oriented and stable, for example `get_employee_by_id`.
26
+ - [ ] Description tells the model when to use the tool.
27
+ - [ ] Inputs are minimal and strongly typed.
28
+ - [ ] Output is a DTO or result object, not an EF entity.
29
+ - [ ] Tool delegates to MediatR or an existing application service.
30
+ - [ ] Errors are structured and safe to show to an AI client.
31
+ - [ ] Cancellation token is accepted and passed through.
32
+ - [ ] New tools are documented in the relevant MCP docs when public usage changes.
33
+
34
+ ## Implementation Shape
35
+
36
+ ```csharp
37
+ [McpTool("get_employee_by_id", "Gets one employee by id.")]
38
+ public static async Task<EmployeeDto?> GetEmployeeByIdAsync(
39
+ Guid employeeId,
40
+ IMediator mediator,
41
+ CancellationToken cancellationToken)
42
+ {
43
+ return await mediator.Send(
44
+ new GetEmployeeByIdQuery(employeeId),
45
+ cancellationToken);
46
+ }
47
+ ```
48
+
49
+ ## Transport Notes
50
+
51
+ - HTTP transport can share ASP.NET Core middleware for auth, validation, logging, and error handling.
52
+ - Stdio transport must not write normal logs to stdout.
53
+ - Keep `mcp.json` entries simple and point to built server artifacts or stable commands.
54
+ - If a client cannot discover tools, verify the server builds, starts, and returns valid MCP initialize/list-tools responses.