feat: add structured logging, Shouldly assertions, CPM, and project documentation
- Add Microsoft.Extensions.Logging + Serilog to NatsServer and NatsClient - Convert all test assertions from xUnit Assert to Shouldly - Add NSubstitute package for future mocking needs - Introduce Central Package Management via Directory.Packages.props - Add documentation_rules.md with style guide, generation/update rules, component map - Generate 10 documentation files across 5 component folders (GettingStarted, Protocol, Subscriptions, Server, Configuration/Operations) - Update CLAUDE.md with logging, testing, porting, agent model, CPM, and documentation guidance
This commit is contained in:
50
CLAUDE.md
50
CLAUDE.md
@@ -145,6 +145,56 @@ Client PUB → parser → permission check → Sublist.Match() →
|
||||
└─ JetStream: if subject matches a stream, store + deliver to consumers
|
||||
```
|
||||
|
||||
## NuGet Package Management
|
||||
|
||||
This solution uses **Central Package Management (CPM)** via `Directory.Packages.props` at the repo root. All package versions are defined centrally there.
|
||||
|
||||
- In `.csproj` files, use `<PackageReference Include="Foo" />` **without** a `Version` attribute
|
||||
- To add a new package: add a `<PackageVersion>` entry in `Directory.Packages.props`, then reference it without version in the project's csproj
|
||||
- To update a version: change it only in `Directory.Packages.props` — all projects pick it up automatically
|
||||
- Never specify `Version` on `<PackageReference>` in individual csproj files
|
||||
|
||||
## Logging
|
||||
|
||||
Use **Microsoft.Extensions.Logging** (`ILogger<T>`) for all logging throughout the server. Wire up **Serilog** as the logging provider in the host application.
|
||||
|
||||
- Inject `ILogger<T>` via constructor in all components (NatsServer, NatsClient, etc.)
|
||||
- Use **Serilog.Context.LogContext** to push contextual properties (client ID, remote endpoint, subscription subject) so they appear on all log entries within that scope
|
||||
- Use structured logging with message templates: `logger.LogInformation("Client {ClientId} subscribed to {Subject}", id, subject)` — never string interpolation
|
||||
- Log levels: `Trace` for protocol bytes, `Debug` for per-message flow, `Information` for lifecycle events (connect/disconnect), `Warning` for protocol violations, `Error` for unexpected failures
|
||||
|
||||
## Testing
|
||||
|
||||
- **xUnit 3** for test framework
|
||||
- **Shouldly** for assertions — use `value.ShouldBe(expected)`, `action.ShouldThrow<T>()`, etc. Do NOT use `Assert.*` from xUnit
|
||||
- **NSubstitute** for mocking/substitution when needed
|
||||
- Do **NOT** use FluentAssertions or Moq — these are explicitly excluded
|
||||
- Test project uses global `using Shouldly;`
|
||||
|
||||
## Porting Guidelines
|
||||
|
||||
- Use modern .NET 10 / C# 14 best practices (primary constructors, collection expressions, `field` keyword where stable, file-scoped namespaces, raw string literals, etc.)
|
||||
- Prefer `readonly record struct` for small value types over mutable structs
|
||||
- Use `required` properties and `init` setters for initialization-only state
|
||||
- Use pattern matching and switch expressions where they improve clarity
|
||||
- Prefer `System.Text.Json` source generators for JSON serialization
|
||||
- Use `ValueTask` where appropriate for hot-path async methods
|
||||
|
||||
## Agent Model Guidance
|
||||
|
||||
- **Sonnet** (`model: "sonnet"`) — use for simpler implementation tasks: straightforward file modifications, adding packages, converting assertions, boilerplate code
|
||||
- **Opus** (default) — use for complex tasks, architectural decisions, design work, tricky protocol logic, and code review
|
||||
- **Parallel subagents** — use where tasks are independent and don't touch the same files (e.g., converting test files in parallel, adding packages while updating docs)
|
||||
|
||||
## Documentation
|
||||
|
||||
Follow the documentation rules in [`documentation_rules.md`](documentation_rules.md) for all project documentation. Key points:
|
||||
|
||||
- Documentation lives in `Documentation/` with component subfolders (Protocol, Subscriptions, Server, Configuration, Operations)
|
||||
- Use `PascalCase.md` file names, always specify language on code blocks, use real code snippets (not invented examples)
|
||||
- Update documentation when code changes — see the trigger rules and component map in the rules file
|
||||
- Technical and direct tone, explain "why" not just "what", present tense
|
||||
|
||||
## Conventions
|
||||
|
||||
- Reference the Go implementation file and line when porting a subsystem
|
||||
|
||||
Reference in New Issue
Block a user