@pratikpsl/agent-skills 0.8.0 → 1.0.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.
- package/README.md +59 -99
- package/dist/bin/agent-skills.d.ts.map +1 -1
- package/dist/bin/agent-skills.js +0 -3
- package/dist/bin/agent-skills.js.map +1 -1
- package/dist/cli/index.js +41 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/core/ide-map.d.ts +3 -9
- package/dist/core/ide-map.d.ts.map +1 -1
- package/dist/core/ide-map.js +16 -33
- package/dist/core/ide-map.js.map +1 -1
- package/dist/core/install-template.d.ts +21 -0
- package/dist/core/install-template.d.ts.map +1 -0
- package/dist/core/install-template.js +119 -0
- package/dist/core/install-template.js.map +1 -0
- package/dist/core/resolve-template.d.ts +4 -0
- package/dist/core/resolve-template.d.ts.map +1 -0
- package/dist/core/resolve-template.js +22 -0
- package/dist/core/resolve-template.js.map +1 -0
- package/package.json +2 -2
- package/templates/default/instructions.md +26 -27
- package/templates/dotnet/AgentSkills/agents/architect.agent.md +8 -54
- package/templates/dotnet/AgentSkills/agents/developer.agent.md +8 -83
- package/templates/dotnet/AgentSkills/skills/csharp-xunit/SKILL.md +32 -58
- package/templates/dotnet/AgentSkills/skills/dotnet-best-practices/SKILL.md +62 -153
- package/templates/dotnet/AgentSkills/skills/performance/SKILL.md +18 -0
- package/templates/react/AgentSkills/agents/developer.agent.md +23 -0
- package/templates/react/AgentSkills/skills/performance/SKILL.md +18 -0
- package/templates/react/AgentSkills/skills/react-typescript/SKILL.md +22 -0
- package/templates/react/AgentSkills/skills/testing/SKILL.md +17 -0
- package/templates/shared/AgentSkills/OPERATING.md +15 -0
- package/templates/shared/AgentSkills/agents/architect.agent.md +12 -0
- package/templates/shared/AgentSkills/agents/reviewer.agent.md +26 -0
- package/templates/shared/AgentSkills/skills/security/SKILL.md +18 -0
- package/templates/shared/AgentSkills/skills/standards/SKILL.md +27 -0
- package/templates/shared/entry-points/instructions.md +24 -0
- package/dist/cli/commands/add.d.ts +0 -3
- package/dist/cli/commands/add.d.ts.map +0 -1
- package/dist/cli/commands/add.js +0 -73
- package/dist/cli/commands/add.js.map +0 -1
- package/dist/cli/commands/dotnet-setup.d.ts +0 -5
- package/dist/cli/commands/dotnet-setup.d.ts.map +0 -1
- package/dist/cli/commands/dotnet-setup.js +0 -83
- package/dist/cli/commands/dotnet-setup.js.map +0 -1
- package/dist/cli/commands/init.d.ts +0 -3
- package/dist/cli/commands/init.d.ts.map +0 -1
- package/dist/cli/commands/init.js +0 -36
- package/dist/cli/commands/init.js.map +0 -1
- package/dist/cli/commands/list.d.ts +0 -3
- package/dist/cli/commands/list.d.ts.map +0 -1
- package/dist/cli/commands/list.js +0 -37
- package/dist/cli/commands/list.js.map +0 -1
- package/dist/cli/commands/setup.d.ts +0 -9
- package/dist/cli/commands/setup.d.ts.map +0 -1
- package/dist/cli/commands/setup.js +0 -77
- package/dist/cli/commands/setup.js.map +0 -1
- package/dist/core/copy-skills.d.ts +0 -30
- package/dist/core/copy-skills.d.ts.map +0 -1
- package/dist/core/copy-skills.js +0 -84
- package/dist/core/copy-skills.js.map +0 -1
- package/dist/core/load-pack.d.ts +0 -15
- package/dist/core/load-pack.d.ts.map +0 -1
- package/dist/core/load-pack.js +0 -35
- package/dist/core/load-pack.js.map +0 -1
- package/dist/core/manifest.d.ts +0 -21
- package/dist/core/manifest.d.ts.map +0 -1
- package/dist/core/manifest.js +0 -170
- package/dist/core/manifest.js.map +0 -1
- package/dist/core/resolve-pack.d.ts +0 -7
- package/dist/core/resolve-pack.d.ts.map +0 -1
- package/dist/core/resolve-pack.js +0 -59
- package/dist/core/resolve-pack.js.map +0 -1
- package/templates/dotnet/AgentSkills/OPERATING.md +0 -85
- package/templates/dotnet/AgentSkills/README.md +0 -64
- package/templates/dotnet/AgentSkills/agents/README.md +0 -16
- package/templates/dotnet/AgentSkills/entry-points/entry-point.md +0 -49
- package/templates/dotnet/AgentSkills/memory/index.md +0 -22
- package/templates/dotnet/AgentSkills/memory/lessons/api.md +0 -3
- package/templates/dotnet/AgentSkills/memory/lessons/auth.md +0 -3
- package/templates/dotnet/AgentSkills/memory/lessons/csharp.md +0 -3
- package/templates/dotnet/AgentSkills/memory/lessons/db.md +0 -3
- package/templates/dotnet/AgentSkills/memory/lessons/design.md +0 -3
- package/templates/dotnet/AgentSkills/memory/lessons/infra.md +0 -8
- package/templates/dotnet/AgentSkills/memory/lessons/mcp.md +0 -3
- package/templates/dotnet/AgentSkills/memory/lessons/testing.md +0 -3
- package/templates/dotnet/AgentSkills/memory/schema.md +0 -26
- package/templates/dotnet/AgentSkills/skills/INDEX.md +0 -21
- package/templates/dotnet/AgentSkills/skills/README.md +0 -14
- package/templates/dotnet/AgentSkills/skills/code-standards/SKILL.md +0 -122
- package/templates/dotnet/AgentSkills/skills/core/SKILL.md +0 -83
- package/templates/dotnet/AgentSkills/skills/design/SKILL.md +0 -108
- package/templates/dotnet/AgentSkills/skills/harness/SKILL.md +0 -62
- package/templates/dotnet/AgentSkills/skills/mcp_dotnet/SKILL.md +0 -54
- package/templates/shared/manifest.json +0 -57
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pratikpsl/agent-skills",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"description": "CLI to scaffold and manage AI agent skills across projects — like shadcn/ui, but for Cursor, Claude, Codex, Copilot, Antigravity, and more",
|
|
6
6
|
"bin": {
|
|
7
7
|
"agent-skills": "dist/bin/agent-skills.js"
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"build": "tsc",
|
|
48
48
|
"test": "vitest run",
|
|
49
49
|
"test:watch": "vitest",
|
|
50
|
-
"dry-run": "
|
|
50
|
+
"dry-run": "npm run build && npm pack --dry-run"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"commander": "^15.0.0"
|
|
@@ -2,36 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
## Goal
|
|
4
4
|
Implement the requested change with production-quality code, preserving existing behavior and
|
|
5
|
-
minimizing the diff, following the project's own architecture and conventions
|
|
6
|
-
told otherwise.
|
|
5
|
+
minimizing the diff, following the project's own architecture and conventions.
|
|
7
6
|
|
|
8
7
|
## Principles
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- Make the smallest change that satisfies the request;
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
8
|
+
|
|
9
|
+
### Scope & Intent
|
|
10
|
+
- Make the smallest change that satisfies the request; touch only what is explicitly required.
|
|
11
|
+
- Do not add unrequested features, speculative abstractions, or unsolicited refactoring (YAGNI).
|
|
12
|
+
- Favor deletion over addition; reuse existing utilities and helpers before creating new ones.
|
|
13
|
+
- If requirements are ambiguous or missing critical details, ask before guessing.
|
|
14
|
+
|
|
15
|
+
### Code Quality & Design
|
|
16
|
+
- Match existing code style, patterns, naming, error handling, and folder structure.
|
|
17
|
+
- Apply SOLID, DRY, and KISS: single-responsibility functions, separation of concerns, no duplicated logic.
|
|
18
|
+
- Keep functions under 50 lines, nesting depth at most 2 levels (prefer early returns), and signatures under 4 parameters.
|
|
19
|
+
- Use meaningful names and named constants/enums (no magic numbers or strings).
|
|
20
|
+
- Design self-describing APIs, structured schemas, and human-/machine-readable contracts.
|
|
21
|
+
- Comment only where non-obvious rationale is required, not what the code already says.
|
|
22
|
+
|
|
23
|
+
### Reliability & Security
|
|
24
|
+
- Never hardcode, commit, or log secrets, credentials, tokens, or sensitive user data.
|
|
25
|
+
- Validate and sanitize external input; use parameterized queries to prevent injection.
|
|
26
|
+
- Use idiomatic non-blocking `async`/`await`; ensure code is free of race conditions and deadlocks.
|
|
27
|
+
- Avoid deprecated APIs and patterns; introduce new dependencies only when strictly necessary (permissive license, actively maintained).
|
|
28
28
|
|
|
29
29
|
## Definition of Done
|
|
30
|
-
- Builds and
|
|
31
|
-
- No debug code, dead code, unused imports, or
|
|
32
|
-
-
|
|
33
|
-
- The change is minimal, focused, and easy to review.
|
|
30
|
+
- Builds cleanly and all tests pass without errors or warnings.
|
|
31
|
+
- No debug code, dead code, unused imports, or temporary files left behind.
|
|
32
|
+
- Changes are minimal, focused, covered by tests, and easy to review.
|
|
34
33
|
|
|
35
34
|
## Agent Memory
|
|
36
|
-
Read `AgentSkills/memory/index.md` at the start of every task; load only
|
|
37
|
-
|
|
35
|
+
- Read `AgentSkills/memory/index.md` at the start of every task (create if missing); load only relevant domain lessons.
|
|
36
|
+
- When a mistake is corrected or a durable rule discovered, record an actionable lesson in `AgentSkills/memory/lessons/<domain>.md` (create if missing) and update `index.md`.
|
|
@@ -1,59 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: architect
|
|
3
|
-
description:
|
|
4
|
-
Load when designing features, planning CQRS structure,
|
|
5
|
-
designing SQL schema, or planning MCP server contracts.
|
|
6
|
-
Do not write implementation code; output structure only.
|
|
3
|
+
description: .NET architectural design, Clean Architecture, CQRS, and API boundaries.
|
|
7
4
|
---
|
|
8
5
|
|
|
9
|
-
# Architect
|
|
6
|
+
# .NET Architect
|
|
10
7
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
- Define
|
|
16
|
-
-
|
|
17
|
-
- Reject designs that violate SOLID, KISS, or YAGNI.
|
|
18
|
-
- Prefer simple, small designs that are easy to delete.
|
|
19
|
-
|
|
20
|
-
## CQRS Rules
|
|
21
|
-
|
|
22
|
-
- Commands mutate state and return nothing, an ID, or a small result.
|
|
23
|
-
- Queries read state and never mutate.
|
|
24
|
-
- Controllers dispatch only; no business logic belongs in controllers.
|
|
25
|
-
- Use one handler per command or query.
|
|
26
|
-
- Query designs returning collections must specify projection, pagination, and tracking behavior.
|
|
27
|
-
|
|
28
|
-
## Output Format
|
|
29
|
-
|
|
30
|
-
Before implementation, produce:
|
|
31
|
-
|
|
32
|
-
1. Command/query split with input and output.
|
|
33
|
-
2. SQL schema if new tables are needed.
|
|
34
|
-
3. MCP tool contract if the MCP surface changes.
|
|
35
|
-
4. Proposed folder structure.
|
|
36
|
-
|
|
37
|
-
## Example Command / Query Split
|
|
38
|
-
|
|
39
|
-
| Type | Name | Input | Output |
|
|
40
|
-
|---|---|---|---|
|
|
41
|
-
| Command | CreateOrderCommand | CreateOrderRequest | OrderId |
|
|
42
|
-
| Query | GetOrderByIdQuery | OrderId | OrderDto |
|
|
43
|
-
|
|
44
|
-
## Example Folder Structure
|
|
45
|
-
|
|
46
|
-
```text
|
|
47
|
-
Features/
|
|
48
|
-
└── Orders/
|
|
49
|
-
├── Commands/
|
|
50
|
-
│ └── CreateOrder/
|
|
51
|
-
│ ├── CreateOrderCommand.cs
|
|
52
|
-
│ ├── CreateOrderHandler.cs
|
|
53
|
-
│ └── CreateOrderValidator.cs
|
|
54
|
-
└── Queries/
|
|
55
|
-
└── GetOrderById/
|
|
56
|
-
├── GetOrderByIdQuery.cs
|
|
57
|
-
├── GetOrderByIdHandler.cs
|
|
58
|
-
└── OrderDto.cs
|
|
59
|
-
```
|
|
8
|
+
## Architectural Principles
|
|
9
|
+
- **Separation of Concerns**: Enforce clean boundaries (Domain, Application, Infrastructure, API).
|
|
10
|
+
- **CQRS Pattern**: Separate commands (mutating state) from queries (read-only projections).
|
|
11
|
+
- **Domain Encapsulation**: Place core business rules in domain entities or domain services; keep API controllers and minimal endpoints thin.
|
|
12
|
+
- **Contract-First Design**: Define relational schemas, entity relationships, indexes, and immutable DTO contracts before implementation.
|
|
13
|
+
- **Protocol Neutrality**: Design application handlers (e.g. MediatR) to serve REST, gRPC, and MCP tools without coupling to transport logic.
|
|
@@ -1,88 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: developer
|
|
3
|
-
description:
|
|
4
|
-
Load when implementing features in .NET C# API.
|
|
5
|
-
Always load architect guidance first if structure is not defined.
|
|
6
|
-
Always follows CQRS and loads code-standards plus dotnet-best-practices.
|
|
3
|
+
description: .NET C# feature implementation, ASP.NET Core APIs, MediatR, and EF Core.
|
|
7
4
|
---
|
|
8
5
|
|
|
9
|
-
# Developer
|
|
6
|
+
# .NET Developer
|
|
10
7
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
- EF Core for persistence.
|
|
18
|
-
- MCP Server SDK for AI tool surface.
|
|
19
|
-
|
|
20
|
-
## Implementation Rules
|
|
21
|
-
|
|
22
|
-
- Use records for commands, queries, and DTOs when immutability is appropriate.
|
|
23
|
-
- Mark classes `sealed` unless inheritance is intentionally supported.
|
|
24
|
-
- Keep controllers thin; they should validate transport concerns and dispatch through MediatR.
|
|
25
|
-
- Keep business rules in domain entities or domain/application services, not controllers or handlers.
|
|
26
|
-
- Use repositories or data access abstractions where the project already follows that convention.
|
|
27
|
-
- Use async all the way; never block with `.Result`, `.Wait()`, or `.GetAwaiter().GetResult()`.
|
|
28
|
-
- Pass `CancellationToken` through request, handler, EF Core, HTTP, and MCP boundaries.
|
|
29
|
-
- Optimize read queries with `.AsNoTracking()`, DTO projection, pagination, and no N+1 queries.
|
|
30
|
-
- Keep API payloads small and avoid excessive logging in hot paths.
|
|
31
|
-
|
|
32
|
-
## CQRS Pattern
|
|
33
|
-
|
|
34
|
-
```csharp
|
|
35
|
-
public sealed record CreateOrderCommand(Guid CustomerId, IReadOnlyList<OrderItem> Items)
|
|
36
|
-
: IRequest<Guid>;
|
|
37
|
-
|
|
38
|
-
public sealed class CreateOrderHandler(IOrderRepository repository)
|
|
39
|
-
: IRequestHandler<CreateOrderCommand, Guid>
|
|
40
|
-
{
|
|
41
|
-
public async Task<Guid> Handle(
|
|
42
|
-
CreateOrderCommand command,
|
|
43
|
-
CancellationToken cancellationToken)
|
|
44
|
-
{
|
|
45
|
-
var order = Order.Create(command.CustomerId, command.Items);
|
|
46
|
-
await repository.AddAsync(order, cancellationToken);
|
|
47
|
-
return order.Id;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Controller Rule
|
|
53
|
-
|
|
54
|
-
Controllers dispatch only.
|
|
55
|
-
|
|
56
|
-
```csharp
|
|
57
|
-
[HttpPost]
|
|
58
|
-
public async Task<IActionResult> Create(
|
|
59
|
-
CreateOrderRequest request,
|
|
60
|
-
CancellationToken cancellationToken)
|
|
61
|
-
{
|
|
62
|
-
var orderId = await mediator.Send(
|
|
63
|
-
new CreateOrderCommand(request.CustomerId, request.Items),
|
|
64
|
-
cancellationToken);
|
|
65
|
-
|
|
66
|
-
return CreatedAtAction(nameof(GetById), new { orderId }, null);
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## MCP Tool Rule
|
|
71
|
-
|
|
72
|
-
MCP tools should reuse the same command/query handlers as REST endpoints.
|
|
73
|
-
|
|
74
|
-
```csharp
|
|
75
|
-
[McpTool("create_order", "Creates a new order")]
|
|
76
|
-
public static async Task<CreateOrderResult> CreateOrderAsync(
|
|
77
|
-
Guid customerId,
|
|
78
|
-
IReadOnlyList<OrderItem> items,
|
|
79
|
-
IMediator mediator,
|
|
80
|
-
CancellationToken cancellationToken)
|
|
81
|
-
{
|
|
82
|
-
var orderId = await mediator.Send(
|
|
83
|
-
new CreateOrderCommand(customerId, items),
|
|
84
|
-
cancellationToken);
|
|
85
|
-
|
|
86
|
-
return new CreateOrderResult(orderId);
|
|
87
|
-
}
|
|
88
|
-
```
|
|
8
|
+
## Implementation Principles
|
|
9
|
+
- **Modern C# Idioms**: Use `record` for immutable DTOs/commands/queries, `sealed` classes by default, and primary constructors where appropriate.
|
|
10
|
+
- **Clean Endpoints**: Keep controllers thin; handle validation and dispatch requests through mediator handlers.
|
|
11
|
+
- **Async & Cancellation**: Use non-blocking `async`/`await` throughout; propagate `CancellationToken` to all EF Core, HTTP, and async calls.
|
|
12
|
+
- **Query Efficiency**: Always use `.AsNoTracking()` for read-only queries, project explicitly to DTOs, and prevent N+1 query patterns.
|
|
13
|
+
- **Complexity Limits**: Keep methods under 50 lines, avoid blocking calls (`.Result`, `.Wait()`), and eliminate magic numbers/strings.
|
|
@@ -1,68 +1,42 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: csharp-xunit
|
|
3
|
-
description:
|
|
3
|
+
description: Best practices for xUnit testing, data-driven theories, mocking, fixtures, and assertions.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# xUnit Best Practices
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Guidelines for writing effective, isolated, and maintainable unit and integration tests with xUnit.
|
|
9
9
|
|
|
10
|
-
## Project Setup
|
|
10
|
+
## Project Setup & Conventions
|
|
11
|
+
- Place tests in a dedicated test project named `[ProjectName].Tests`.
|
|
12
|
+
- Reference `Microsoft.NET.Test.Sdk`, `xunit`, and `xunit.runner.visualstudio`.
|
|
13
|
+
- Match test class names to the class under test (e.g., `OrderServiceTests` for `OrderService`).
|
|
14
|
+
- Execute tests via standard CLI: `dotnet test`.
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
- Use
|
|
16
|
+
## Test Structure & Naming
|
|
17
|
+
- Follow the **Arrange-Act-Assert (AAA)** pattern.
|
|
18
|
+
- Use the standard naming convention: `MethodName_Scenario_ExpectedBehavior`.
|
|
19
|
+
- Use constructors for test initialization and `IDisposable.Dispose()` for teardown.
|
|
20
|
+
- Use `IClassFixture<T>` for shared context across tests in a single class.
|
|
21
|
+
- Use `ICollectionFixture<T>` for shared context across multiple test classes.
|
|
16
22
|
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- Use constructor for setup and `IDisposable.Dispose()` for teardown
|
|
24
|
-
- Use `IClassFixture<T>` for shared context between tests in a class
|
|
25
|
-
- Use `ICollectionFixture<T>` for shared context between multiple test classes
|
|
26
|
-
|
|
27
|
-
## Standard Tests
|
|
28
|
-
|
|
29
|
-
- Keep tests focused on a single behavior
|
|
30
|
-
- Avoid testing multiple behaviors in one test method
|
|
31
|
-
- Use clear assertions that express intent
|
|
32
|
-
- Include only the assertions needed to verify the test case
|
|
33
|
-
- Make tests independent and idempotent (can run in any order)
|
|
34
|
-
- Avoid test interdependencies
|
|
35
|
-
|
|
36
|
-
## Data-Driven Tests
|
|
37
|
-
|
|
38
|
-
- Use `[Theory]` combined with data source attributes
|
|
39
|
-
- Use `[InlineData]` for inline test data
|
|
40
|
-
- Use `[MemberData]` for method-based test data
|
|
41
|
-
- Use `[ClassData]` for class-based test data
|
|
42
|
-
- Create custom data attributes by implementing `DataAttribute`
|
|
43
|
-
- Use meaningful parameter names in data-driven tests
|
|
23
|
+
## Fact vs. Theory Tests
|
|
24
|
+
- **`[Fact]`**: For single-condition tests verifying one specific behavior.
|
|
25
|
+
- **`[Theory]`**: For data-driven tests testing multiple inputs and edge cases.
|
|
26
|
+
- `[InlineData(arg1, arg2)]`: For simple scalar test cases.
|
|
27
|
+
- `[MemberData(nameof(TestDataMethod))]`: For complex or generated test objects.
|
|
28
|
+
- `[ClassData(typeof(CustomTestDataClass))]`: For reusable external test datasets.
|
|
44
29
|
|
|
45
30
|
## Assertions
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
-
|
|
58
|
-
- Mock dependencies to isolate units under test
|
|
59
|
-
- Use interfaces to facilitate mocking
|
|
60
|
-
- Consider using a DI container for complex test setups
|
|
61
|
-
|
|
62
|
-
## Test Organization
|
|
63
|
-
|
|
64
|
-
- Group tests by feature or component
|
|
65
|
-
- Use `[Trait("Category", "CategoryName")]` for categorization
|
|
66
|
-
- Use collection fixtures to group tests with shared dependencies
|
|
67
|
-
- Consider output helpers (`ITestOutputHelper`) for test diagnostics
|
|
68
|
-
- Skip tests conditionally with `Skip = "reason"` in fact/theory attributes
|
|
31
|
+
- Use specific assertions expressing intent:
|
|
32
|
+
- Values: `Assert.Equal(expected, actual)`, `Assert.NotEqual(...)`
|
|
33
|
+
- References: `Assert.Same(expected, actual)`
|
|
34
|
+
- Conditions: `Assert.True(condition)`, `Assert.False(condition)`
|
|
35
|
+
- Collections: `Assert.Contains(item, list)`, `Assert.DoesNotContain(...)`
|
|
36
|
+
- Exceptions: `Assert.Throws<T>(() => ...)` or `await Assert.ThrowsAsync<T>(() => ...)`
|
|
37
|
+
- Alternatively, use `FluentAssertions` where it improves assertion readability.
|
|
38
|
+
|
|
39
|
+
## Isolation & Mocking
|
|
40
|
+
- Mock external dependencies and I/O boundaries using Moq or NSubstitute.
|
|
41
|
+
- Code against interfaces to enable clean mock substitution.
|
|
42
|
+
- Keep tests isolated, independent, and idempotent (no reliance on execution order or external state).
|
|
@@ -8,163 +8,72 @@ description: >
|
|
|
8
8
|
|
|
9
9
|
# .NET/C# Best Practices
|
|
10
10
|
|
|
11
|
-
Use this skill to keep .NET/C# changes simple, maintainable, testable, and aligned with
|
|
12
|
-
|
|
13
|
-
## Repository Defaults
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
11
|
+
Use this skill to keep .NET/C# changes simple, maintainable, testable, and aligned with repository conventions.
|
|
12
|
+
|
|
13
|
+
## Repository Defaults & Structure
|
|
14
|
+
- Follow target framework and language versions in `Directory.Build.props` (default `net10.0`, `LangVersion` `latest`).
|
|
15
|
+
- Add XML documentation comments for public/shared API surfaces.
|
|
16
|
+
- Organize code by feature or domain slices; place controllers, handlers, validators, repositories, and DTOs predictably.
|
|
17
|
+
- Prefer clear, direct code over complex or speculative patterns (YAGNI).
|
|
18
|
+
|
|
19
|
+
## CQRS & Architecture
|
|
20
|
+
- **Commands**: Mutate state; return void, an identifier, or a minimal result.
|
|
21
|
+
- **Queries**: Read state only; never mutate data.
|
|
22
|
+
- **Thin Endpoints**: Keep controllers and minimal API endpoints thin; validate transport concerns and dispatch via mediator handlers.
|
|
23
|
+
- **Domain Logic**: Encapsulate domain rules in domain entities or domain services, never in transport handlers.
|
|
24
|
+
- **Immutability**: Use `record` for commands, queries, and DTOs; mark classes `sealed` unless inheritance is intentionally designed.
|
|
25
|
+
- **Interfaces**: Define interfaces for boundaries requiring testing, multiple implementations, or out-of-process integration.
|
|
26
|
+
|
|
27
|
+
## Dependency Injection & Lifetimes
|
|
42
28
|
- Use constructor injection or primary constructors for required dependencies.
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
- `
|
|
46
|
-
- `
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
-
|
|
57
|
-
- Use
|
|
58
|
-
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
29
|
+
- Register services with the narrowest appropriate lifetime:
|
|
30
|
+
- `Singleton`: Stateless, thread-safe services.
|
|
31
|
+
- `Scoped`: Request-bound services and EF Core `DbContext`.
|
|
32
|
+
- `Transient`: Lightweight, stateless operations.
|
|
33
|
+
- Avoid resolving services manually via `IServiceProvider` or introducing static global state.
|
|
34
|
+
|
|
35
|
+
## Async & I/O
|
|
36
|
+
- Use `async`/`await` for all I/O, database, network, and file operations.
|
|
37
|
+
- Never block async code using `.Result`, `.Wait()`, or `.GetAwaiter().GetResult()`.
|
|
38
|
+
- Accept and propagate `CancellationToken` through all handler, EF Core, and outbound HTTP calls.
|
|
39
|
+
- Avoid `async void` except for top-level event handlers.
|
|
40
|
+
|
|
41
|
+
## EF Core & Data Access
|
|
42
|
+
- Avoid N+1 queries by using explicit projections, `.Include()`, or separate optimized queries.
|
|
43
|
+
- Use `.AsNoTracking()` for all read-only queries.
|
|
44
|
+
- Select only needed columns into DTOs instead of loading full tracked entities.
|
|
45
|
+
- Implement server-side pagination, filtering, and sorting; never filter unbounded sets in memory.
|
|
46
|
+
- Prefer `AnyAsync()` over `CountAsync()` when testing for existence.
|
|
47
|
+
- Use `ExecuteUpdateAsync` and `ExecuteDeleteAsync` for bulk operations where appropriate.
|
|
48
|
+
|
|
49
|
+
## Logging & Observability
|
|
50
|
+
- Use structured logging with message templates and named properties (`LogInformation("Order {OrderId} processed", id)`).
|
|
51
|
+
- Avoid logging inside tight loops or hot execution paths.
|
|
52
|
+
- Propagate correlation/request IDs across service and HTTP boundaries.
|
|
53
|
+
- Never log secrets, passwords, connection strings, or sensitive personal data (PII).
|
|
54
|
+
|
|
55
|
+
## HTTP & Resilient Integration
|
|
125
56
|
- Use `IHttpClientFactory` for outbound HTTP calls.
|
|
126
|
-
- Set timeouts and pass cancellation tokens.
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
- Prefer resilient integration patterns for unreliable dependencies.
|
|
57
|
+
- Set explicit timeouts and pass cancellation tokens to all HTTP calls.
|
|
58
|
+
- Use bounded retries with exponential backoff for transient failures; avoid unbounded retry storms.
|
|
59
|
+
- Batch outbound requests rather than making external calls inside tight loops.
|
|
130
60
|
|
|
131
|
-
## Security
|
|
132
|
-
|
|
133
|
-
-
|
|
134
|
-
-
|
|
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.
|
|
61
|
+
## Security & Validation
|
|
62
|
+
- Validate all incoming request payloads using FluentValidation or Data Annotations.
|
|
63
|
+
- Never concatenate raw user input into SQL queries, shell commands, or file paths.
|
|
64
|
+
- Follow the principle of least privilege for database connections and external service credentials.
|
|
138
65
|
|
|
139
66
|
## Testing Standards
|
|
140
|
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
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.
|
|
67
|
+
- Use xUnit for unit and integration testing.
|
|
68
|
+
- Structure tests using Arrange-Act-Assert (AAA).
|
|
69
|
+
- Test happy paths, edge cases, validation failures, and cancellation flows.
|
|
70
|
+
- Keep tests isolated, deterministic, and idempotent.
|
|
156
71
|
|
|
157
72
|
## Review Checklist
|
|
158
|
-
|
|
159
|
-
- [ ]
|
|
160
|
-
- [ ]
|
|
161
|
-
- [ ]
|
|
162
|
-
- [ ]
|
|
163
|
-
- [ ]
|
|
164
|
-
- [ ]
|
|
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.
|
|
73
|
+
- [ ] No N+1 queries; read-only EF Core queries use `.AsNoTracking()`.
|
|
74
|
+
- [ ] DTO projections used; no full entity graphs exposed to callers.
|
|
75
|
+
- [ ] Async methods propagate `CancellationToken` without blocking.
|
|
76
|
+
- [ ] DI lifetimes correctly configured (`Scoped` for DbContext).
|
|
77
|
+
- [ ] Structured logging used without leaking sensitive data or secrets.
|
|
78
|
+
- [ ] Input validation applied at boundaries.
|
|
79
|
+
- [ ] Tests pass and cover edge cases.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: performance
|
|
3
|
+
description: .NET memory allocation reduction, Span/ReadOnlySpan, EF Core query tuning, and async efficiency.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# .NET Performance
|
|
7
|
+
|
|
8
|
+
## Memory & Allocation Optimization
|
|
9
|
+
- Minimize heap allocations in hot paths using `ReadOnlySpan<T>`, `Span<T>`, and `Memory<T>`.
|
|
10
|
+
- Use `ValueTask<T>` for asynchronous methods that frequently complete synchronously.
|
|
11
|
+
- Avoid boxing value types and eliminate unnecessary LINQ allocations inside tight loops.
|
|
12
|
+
- Use `ArrayPool<T>` or `StringBuilder` for buffer reuse in repetitive or large text/byte operations.
|
|
13
|
+
|
|
14
|
+
## Database & I/O Efficiency
|
|
15
|
+
- Always use `.AsNoTracking()` for read-only EF Core queries to eliminate change tracking overhead.
|
|
16
|
+
- Use explicit projection (`.Select(x => new ... )`) to fetch only necessary database columns into DTOs.
|
|
17
|
+
- Stream large result sets using `IAsyncEnumerable<T>` instead of buffering entire collections in memory.
|
|
18
|
+
- Avoid N+1 queries by using explicit joins, `.Include()`, or split queries where cartesian explosion is a risk.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: developer
|
|
3
|
+
description: React feature implementation, custom hooks, and state architecture.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# React Developer
|
|
7
|
+
|
|
8
|
+
## Component & State Principles
|
|
9
|
+
- Keep components focused on a single UI responsibility; decompose complex trees.
|
|
10
|
+
- Type props and state strictly using TypeScript discriminated unions for variant states.
|
|
11
|
+
- Colocate state with the closest consuming component; compute derived values during render.
|
|
12
|
+
- Use `useEffect` strictly for external synchronization and always return a cleanup function.
|
|
13
|
+
- Avoid speculative memoization (`useMemo`/`useCallback`) unless measured performance profiling justifies it.
|
|
14
|
+
|
|
15
|
+
## User Interface & Accessibility
|
|
16
|
+
- Build with semantic HTML elements (`<button>`, `<dialog>`, `<form>`, `<nav>`) by default.
|
|
17
|
+
- Use `useId` for unique, accessible form controls and ARIA associations.
|
|
18
|
+
- Ensure all interactive elements have accessible names and visible focus states.
|
|
19
|
+
- Handle loading, empty, and error boundary states explicitly at the feature level.
|
|
20
|
+
|
|
21
|
+
## Async & Resource Safety
|
|
22
|
+
- Use non-blocking `async`/`await` with `AbortController` signal propagation for cancellable data fetching.
|
|
23
|
+
- Clean up active subscriptions, intervals/timers, and abort controllers on component unmount.
|