# Agent Guidelines for Klab.Toolkit This document provides essential guidelines for AI coding agents working on the Klab.Toolkit .NET library collection. ## General Principles * Conciseness: Write clear and concise code that is easy to read and maintain. * No summary comments: Avoid adding summary comments to methods and classes. The code should be self-explanatory. * No summary of changes: Do not include a summary of changes in the response of the prompt. Focus on the code changes themselves. * No explanations: Do not provide explanations or justifications for the code changes. The code should speak for itself. * No comments: Avoid adding comments to the code unless absolutely necessary for clarity. * Dont run commands without explicit instruction or permission: Do not execute any commands or scripts without explicit instruction or permission from the user. Always ask for confirmation before running any code that could have side effects. ## Build, Test, and Lint Commands ### Setup ```bash # Install required global tools (dotnet-format, dotnet-coverage) just setup ``` ### Build ```bash # Build in Debug mode (default) just build # Build in Release mode just build Release # Using dotnet CLI directly dotnet build -c Debug dotnet build -c Release ``` ### Test ```bash # Run all tests with coverage (output to ./tmp) just test # Run tests with custom report path just test ./my-reports # Run a single test project dotnet test src/Klab.Toolkit.Common.Tests/Klab.Toolkit.Common.Tests.csproj # Run a single test method (xUnit) dotnet test --filter "FullyQualifiedName=Klab.Toolkit.Event.Tests.EventBusTests.PublishAsync_WithValidEvent_CallsHandler" # Run a single test method (MSTest) dotnet test --filter "FullyQualifiedName=Klab.Toolkit.Common.Tests.RetryServiceTests.RetryAsync_Success" # Using dotnet CLI directly with coverage dotnet coverage collect -f xml -o ./tmp/coverage.xml "dotnet test" ``` ### Format and Lint ```bash # Format code just format # Check formatting without making changes just check-format # Using dotnet-format directly dotnet format dotnet format --verify-no-changes ``` ### Clean ```bash # Clean build artifacts just clean # Using dotnet CLI dotnet clean ``` ### Restore ```bash # Restore NuGet packages just restore # Using dotnet CLI dotnet restore ``` ## Project Structure - **Solution**: `KlabDotnetToolkit.sln` - **Source**: All projects (libraries and tests) are in `src/` directory - **Libraries**: Target .NET Standard 2.1 for maximum compatibility - **Tests**: Target .NET 9.0 and use xUnit frameworks - **Build Automation**: Uses [Just](https://github.com/casey/just) command runner ### Project Naming Convention - Library: `Klab.Toolkit.[ModuleName]` - Tests: `Klab.Toolkit.[ModuleName].Tests` - Namespace matches project name ## Code Style Guidelines ### File Structure ```csharp using System; using Microsoft.Extensions.DependencyInjection; namespace Klab.Toolkit.ModuleName; /// /// XML documentation is required for all public types and members. /// public class MyClass { private readonly ILogger _logger; public MyClass(ILogger logger) { _logger = logger; } } ``` ### Key Conventions 1. **Namespaces**: Use file-scoped namespaces (enforced) ```csharp namespace Klab.Toolkit.ModuleName; // Correct ``` 2. **Using Directives**: Place outside namespace (enforced), sort System directives first ```csharp using System; using System.Collections.Generic; using Microsoft.Extensions.DependencyInjection; namespace Klab.Toolkit.ModuleName; ``` 3. **Type Inference**: Avoid `var`, use explicit types (warning level) ```csharp IServiceCollection services = new ServiceCollection(); // Correct var services = new ServiceCollection(); // Avoid ``` 4. **Naming Conventions**: - Private fields: `_camelCase` with underscore prefix (enforced) - Public/protected/internal: `PascalCase` - Parameters/locals: `camelCase` - Interfaces: `IPascalCase` (enforced) - Type parameters: `TPascalCase` (enforced) - Constants: `PascalCase` regardless of accessibility 5. **Expression-bodied Members**: - Properties/accessors: Allowed when single line - Methods/constructors: Prefer block body ```csharp public string Name => _name; // Good for properties public void DoWork() { /* multiple lines */ } // Prefer block for methods ``` 6. **Braces**: Always use braces for control statements (suggestion) ```csharp if (condition) { DoSomething(); } ``` 7. **Indentation**: 4 spaces for C# files 8. **Line Endings**: CRLF for C# files, LF for shell scripts 9. **Encoding**: UTF-8 with BOM for code files 10. **Modern C# Features**: Use latest C# features - File-scoped namespaces ✅ - Record types for immutable data ✅ - Pattern matching ✅ - Nullable reference types ✅ (enabled for libraries, disabled for tests) - Top-level statements ✅ ### Dependency Injection Pattern Every library project should expose a `DependencyInjection.cs` file with extension methods: ```csharp namespace Klab.Toolkit.ModuleName; [ExcludeFromCodeCoverage] public static class DependencyInjection { /// /// Adds all Klab.Toolkit.ModuleName services to the service collection. /// public static IServiceCollection AddKlabToolkitModuleName(this IServiceCollection services) { // Register services return services; } } ``` ### Error Handling Use the Result pattern from `Klab.Toolkit.Results` for business logic errors instead of exceptions: ```csharp public Result GetUser(int id) { if (id <= 0) return ErrorGeneric.NotFound("User", id.ToString()); // ... logic return Result.Success(user); } ``` ### Documentation - XML documentation is **required** for all public types and members (enforced) - Treat documentation warnings as errors - Each library includes its `Readme.md` in the NuGet package ## Testing Guidelines 1. **Test Frameworks**: Both MSTest and xUnit are used - Some projects use MSTest (`[TestClass]`, `[TestMethod]`) - Others use xUnit (`[Fact]`, `[Theory]`) 2. **Assertion Libraries**: Use FluentAssertions ```csharp result.Should().BeTrue(); value.Should().Be(expected); ``` 3. **Mocking**: Use NSubstitute ```csharp var mock = Substitute.For(); mock.GetData().Returns(expectedData); ``` 4. **Test Organization**: Mirror library structure in test projects 5. **Coverage**: Tests generate coverage reports in `./tmp/` using coverlet ## Design Philosophy 1. **Modularity**: Each package is independently consumable 2. **Functional Programming**: Leverage Result pattern, immutability, pure functions 3. **Testability**: All abstractions have interfaces for dependency injection 4. **Explicit over Implicit**: Clear error handling, explicit types 5. **Documentation**: Comprehensive XML docs and README files ## CI/CD - **CI Pipeline**: Runs on push/PR to main (format check, build, test, SonarQube) - **CD Pipeline**: Triggered by version tags (`V*.*.*`) for NuGet publishing - **Code Quality**: SonarQube integration for static analysis - **Warnings as Errors**: All warnings are treated as errors in production code ## Common Package References All production projects automatically include: - `Microsoft.Extensions.DependencyInjection.Abstractions` (9.0.2) - `Microsoft.Extensions.Logging.Abstractions` (9.0.2) - `Microsoft.CodeAnalysis.NetAnalyzers` (9.0.0) All test projects automatically include: - MSTest (2.2.10) - xUnit (2.8.0) - FluentAssertions (6.10.0) - NSubstitute (5.1.0) - coverlet.collector (3.1.2) ## Important Notes - **No public fields**: Use properties instead (enforced for non-static) - **Nullable contexts**: Enabled for libraries, disabled for tests - **Package generation**: Automatic on build for library projects - **Platform target**: AnyCPU for libraries, X64 for tests - **License**: MIT (included in all packages)