From 0c218b7abca35e3bbb41ee98051cf4bdc0e56b13 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Fri, 12 Jun 2026 20:40:52 +0000 Subject: [PATCH] Unify agent instructions into AGENTS.md (CLAUDE.md symlink) Merges the contents of AGENT.md and CLAUDE.md into a single canonical AGENTS.md (the cross-tool standard filename), and makes CLAUDE.md a symlink to it so both names resolve to the same guidance. Folds in the unique sections that previously lived only in AGENT.md (Git workflow, API approvals, detailed TestKit guidance, repository conventions) and reconciles the TestKit guidance to the async-only rule. Removes the non-standard singular AGENT.md. --- AGENT.md | 74 ---------------------- AGENTS.md | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 146 +------------------------------------------ 3 files changed, 185 insertions(+), 219 deletions(-) delete mode 100644 AGENT.md create mode 100644 AGENTS.md mode change 100644 => 120000 CLAUDE.md diff --git a/AGENT.md b/AGENT.md deleted file mode 100644 index 622aa90a130..00000000000 --- a/AGENT.md +++ /dev/null @@ -1,74 +0,0 @@ -# Akka.NET Agent Guidelines - -## Build/Test Commands -- Build solution: `dotnet build` -- Build with warnings as errors: `dotnet build -warnaserror` -- Run all tests: `dotnet test -c Release` -- Run specific test: `dotnet test -c Release --filter DisplayName="TestName"` or `dotnet test path/to/project.csproj` -- Format check: `dotnet format --verify-no-changes` - -## Git Repository Management -- Setup remotes: - - `git remote add upstream https://github.com/akkadotnet/akka.net.git` (main repository) - - `git remote add origin https://github.com/yourusername/akka.net.git` (your fork) -- Sync with upstream: - - `git fetch upstream` (get latest changes from main repo) - - `git checkout dev` (switch to dev branch) - - `git merge upstream/dev` (merge changes from upstream) - - `git push origin dev` (update your fork) -- Create feature branch: - - `git checkout -b feature/your-feature-name` (create and switch to new branch) - - `git push -u origin feature/your-feature-name` (push branch to your fork) - -## Code Style Guidelines -- Use Allman style brackets for C# code (opening brace on new line) -- 4 spaces for indentation -- Prefer "var" everywhere when type is apparent -- Private fields start with `_` (underscore), PascalCase for public/protected members -- No "this." qualifier when unnecessary -- Use exceptions for error handling (IllegalStateException for invalid states) -- Sort using statements with System.* appearing first -- XML comments for public APIs -- Name tests with descriptive `DisplayName=` attributes -- Default to `sealed` classes and records for data objects -- Enable nullability in new/modified files with `#nullable enable` -- Never use `async void`, `.Result`, or `.Wait()` - these cause deadlocks -- Always pass `CancellationToken` in async methods - -## API Approvals -- Run API approval tests when making public API changes: `dotnet test -c Release src/core/Akka.API.Tests` -- Approval files are located at `src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt` -- Install a diff viewer like WinMerge or TortoiseMerge to approve API changes -- Follow extend-only design principles - don't modify existing public APIs, only extend them -- Mark deprecated APIs with `[Obsolete("Obsolete since v{current-akka-version}")]` - -## Conventions -- Stay close to JVM Akka where applicable but be .NET idiomatic -- Use Task instead of Future, TimeSpan instead of Duration -- Include unit tests with changes -- Preserve public API and wire compatibility -- Keep pull requests small and focused (<300 lines when possible) -- Fix warnings instead of suppressing them -- Treat TBD comments as action items to be resolved -- Benchmark performance-critical code changes with BenchmarkDotNet -- Avoid adding new dependencies without license/security checks - -## Akka.NET TestKit Guidelines -- Actor tests should derive from `AkkaSpec` or `TestKit` to access actor testing facilities -- Pass `ITestOutputHelper output` to the constructor and base constructor: `public MySpec(ITestOutputHelper output) : base(config, output)` -- Use the `ITestOutputHelper` output for debugging: it captures all test output including actor system logs -- Configure proper logging in tests: `akka.loglevel = DEBUG` or `akka.loglevel = INFO` -- Use `EventFilter` to assert on log messages (e.g., `EventFilter.Error().ExpectOne(() => { /* test code */ });`) -- For testing deadletters, use `EventFilter.DeadLetter().Expect(1, () => { /* code that should produce dead letter */ });` -- Test message assertions using `ExpectMsg()`, `ExpectNoMsg()`, or `FishForMessage()` -- Set explicit timeouts for message expectations to avoid long-running tests -- Use `TestProbe` to create lightweight test actors to verify interactions -- Tests should clean up after themselves (stop created actors, reset state) -- To test specialized message types, verify the type wrapper in logs: `wrapped in [$TypeName]` - -## Repository Landmarks -- `src/` - All runtime / library code -- `src/benchmark/` - Micro-benchmarks (BenchmarkDotNet) -- `src/…Tests/` - xUnit test projects -- `docs/community/contributing/` - Contributor policies & style guides -- `docs/` - Public facing documentation \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..1f838a3f433 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,184 @@ +# AGENTS.md + +This file provides guidance to Claude Code (claude.ai/code) and other coding agents when +working with code in this repository. `CLAUDE.md` is a symlink to this file, so both names +resolve to the same guidance. + +## Build and Test Commands + +### Building the Solution +```bash +# Standard build +dotnet build +dotnet build -c Release + +# Build with warnings as errors (CI validation) +dotnet build -warnaserror +``` + +### Running Tests +```bash +# Run all tests +dotnet test -c Release + +# Run tests for specific framework +dotnet test -c Release --framework net8.0 +dotnet test -c Release --framework net48 + +# Run specific test by name +dotnet test -c Release --filter DisplayName="TestName" + +# Run tests in a specific project +dotnet test path/to/project.csproj -c Release +``` + +### Incremental Testing (for changed code only) +```bash +# Run only unit tests for changed projects +dotnet incrementalist run --config .incrementalist/testsOnly.json -- test -c Release --no-build --framework net8.0 + +# Run only multi-node tests for changed projects +dotnet incrementalist run --config .incrementalist/mutliNodeOnly.json -- test -c Release --no-build --framework net8.0 +``` + +### Code Quality +```bash +# Format check +dotnet format --verify-no-changes + +# API compatibility check +dotnet test -c Release src/core/Akka.API.Tests +``` + +### Documentation +```bash +# Generate API documentation +dotnet docfx metadata ./docs/docfx.json --warningsAsErrors +dotnet docfx build ./docs/docfx.json --warningsAsErrors +``` + +### API Approvals +- Run API approval tests when making public API changes: `dotnet test -c Release src/core/Akka.API.Tests` +- Approval files live at `src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt` (and sibling `*.approved.txt` files) +- A diff viewer (WinMerge, TortoiseMerge, etc.) makes reviewing/approving API changes easier +- Follow **extend-only** design — don't modify existing public APIs, only extend them +- Mark deprecated APIs with `[Obsolete("Obsolete since v{current-akka-version}")]` + +## High-Level Architecture + +### Project Structure +- **`/src/core/`** - Core actor framework components + - `Akka/` - Base actor system, routing, dispatchers, configuration + - `Akka.Remote/` - Distributed actor communication and serialization + - `Akka.Cluster/` - Clustering, gossip protocols, distributed coordination + - `Akka.Persistence/` - Event sourcing, snapshots, journals + - `Akka.Streams/` - Reactive streams with backpressure + - `Akka.TestKit/` - Testing utilities for actor systems +- **`/src/contrib/`** - Contributed modules (DI integrations, serializers, cluster extensions) +- **`/src/benchmark/`** - Performance benchmarks using BenchmarkDotNet +- **`/src/examples/`** - Sample applications demonstrating patterns +- **`/src/**/*.Tests/`** - xUnit test projects +- **`/docs/`** - Public-facing documentation; contributor policies and style guides live under `docs/community/contributing/` + +### Key Architectural Concepts +- **Actor Model**: Message-driven, hierarchical supervision, location transparency +- **Fault Tolerance**: Supervision strategies, let-it-crash philosophy +- **Distribution**: Remote actors, clustering, sharding +- **Reactive Streams**: Backpressure-aware stream processing +- **Event Sourcing**: Persistence with journals and snapshots + +## Code Style and Conventions + +### C# Style +- Allman style braces (opening brace on new line) +- 4 spaces indentation, no tabs +- Private fields prefixed with underscore `_fieldName`; PascalCase for public/protected members +- Use `var` when the type is apparent +- No `this.` qualifier unless necessary +- Sort `using` statements with `System.*` first +- XML doc comments on public APIs +- Default to `sealed` classes and records +- Enable `#nullable enable` in new/modified files +- Never use `async void`, `.Result`, or `.Wait()` — these cause deadlocks +- Always pass `CancellationToken` through async call chains + +### API Design +- Maintain compatibility with JVM Akka while being .NET idiomatic +- Use `Task` instead of Future, `TimeSpan` instead of Duration +- Extend-only design - don't modify existing public APIs +- Preserve wire format compatibility for serialization +- Include unit tests with all changes + +### Test Naming +- Use `DisplayName` attribute for descriptive test names +- Follow pattern: `Should_ExpectedBehavior_When_Condition` + +### General Conventions +- Keep pull requests small and focused (< 300 lines when possible) +- Fix warnings instead of suppressing them +- Treat `TBD` comments as action items to be resolved +- Benchmark performance-critical changes with BenchmarkDotNet +- Avoid adding new dependencies without a license/security check + +## Akka.NET TestKit Guidelines +- Actor tests should derive from `AkkaSpec` or `TestKit` to access actor-testing facilities +- **Always use async TestKit methods** (e.g. `ExpectMsgAsync`, `ExpectNoMsgAsync`, `AwaitAssertAsync`, `FishForMessageAsync`, `ResolveOne`) — never the synchronous variants (`ExpectMsg`, `ExpectNoMsg`, `AwaitAssert`, `.Result`, `.Wait()`) +- Pass `ITestOutputHelper output` to the test constructor and forward it to the base: `public MySpec(ITestOutputHelper output) : base(config, output)` — this captures all test output, including actor-system logs +- Configure logging in tests as needed: `akka.loglevel = DEBUG` or `akka.loglevel = INFO` +- Use `EventFilter` to assert on log messages (e.g. `await EventFilter.Error().ExpectOneAsync(async () => { /* test code */ })`) +- For dead letters, use `EventFilter.DeadLetter()` (e.g. `await EventFilter.DeadLetter().ExpectAsync(1, async () => { /* code that should dead-letter */ })`) +- Use `TestProbe` for lightweight test actors to verify interactions +- Set explicit timeouts on message expectations to avoid long-running tests +- Tests should clean up after themselves (stop created actors, reset state) +- Multi-node tests live in separate `*.Tests.MultiNode.csproj` projects +- To verify specialized message wrappers, check the log form `wrapped in [$TypeName]` + +## Development Workflow + +### Git Branches +- **`dev`** - Main development branch (default for PRs) +- **`v1.4`**, **`v1.3`**, etc. - Version maintenance branches for older releases +- Feature branches: `feature/description` +- Bugfix branches: `fix/description` + +### Git Repository Management +- Remotes: + - `akkadotnet` / `upstream` → `https://github.com/akkadotnet/akka.net.git` (main repository) + - `origin` → your fork (e.g. `https://github.com/yourusername/akka.net.git`) +- Sync with upstream: + - `git fetch akkadotnet` (or `upstream`) + - `git checkout dev` + - `git merge akkadotnet/dev` +- Create a feature branch: + - `git checkout -b feature/your-feature-name` + - `git push -u origin feature/your-feature-name` + +### Making Changes +1. Always read existing code patterns in the module you're modifying +2. Follow existing conventions for that specific module +3. Add/update tests for your changes +4. Run incremental tests before committing +5. Ensure API compatibility tests pass for core changes +6. If the change is breaking, record it in `BREAKING_CHANGES_V1.6.md` in the same change (see below) + +### Tracking Breaking Changes (v1.6 cycle) +Until a stable **v1.6.0** ships, **every** change that goes into the `dev` branch and +introduces a **breaking behavior, wire-format, or public-API change** MUST be documented in +[`BREAKING_CHANGES_V1.6.md`](BREAKING_CHANGES_V1.6.md) (repo root), in the **same PR** that +makes the change. Use the entry format described in that file (status, component, type, +change, migration). This ledger is retired once `v1.6.0` is released, when its contents are +folded into the release notes / upgrade guide. + +### Target Frameworks +- **.NET 8.0** - Primary target +- **.NET 6.0** - Library compatibility +- **.NET Framework 4.8** - Legacy support +- **.NET Standard 2.0** - Library compatibility + +## Important Files +- `Directory.Build.props` - MSBuild properties, package versions +- `global.json` - .NET SDK version (8.0.403) +- `xunit.runner.json` - Test configuration (60s timeout, no parallelization) +- `.incrementalist/*.json` - Incremental build configurations +- `RELEASE_NOTES.md` - Version history and changelog +- `BREAKING_CHANGES_V1.6.md` - Running list of v1.6 breaking changes (until v1.6.0 ships) diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index fde0ba85dfd..00000000000 --- a/CLAUDE.md +++ /dev/null @@ -1,145 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Build and Test Commands - -### Building the Solution -```bash -# Standard build -dotnet build -dotnet build -c Release - -# Build with warnings as errors (CI validation) -dotnet build -warnaserror -``` - -### Running Tests -```bash -# Run all tests -dotnet test -c Release - -# Run tests for specific framework -dotnet test -c Release --framework net8.0 -dotnet test -c Release --framework net48 - -# Run specific test by name -dotnet test -c Release --filter DisplayName="TestName" - -# Run tests in a specific project -dotnet test path/to/project.csproj -c Release -``` - -### Incremental Testing (for changed code only) -```bash -# Run only unit tests for changed projects -dotnet incrementalist run --config .incrementalist/testsOnly.json -- test -c Release --no-build --framework net8.0 - -# Run only multi-node tests for changed projects -dotnet incrementalist run --config .incrementalist/mutliNodeOnly.json -- test -c Release --no-build --framework net8.0 -``` - -### Code Quality -```bash -# Format check -dotnet format --verify-no-changes - -# API compatibility check -dotnet test -c Release src/core/Akka.API.Tests -``` - -### Documentation -```bash -# Generate API documentation -dotnet docfx metadata ./docs/docfx.json --warningsAsErrors -dotnet docfx build ./docs/docfx.json --warningsAsErrors -``` - -## High-Level Architecture - -### Project Structure -- **`/src/core/`** - Core actor framework components - - `Akka/` - Base actor system, routing, dispatchers, configuration - - `Akka.Remote/` - Distributed actor communication and serialization - - `Akka.Cluster/` - Clustering, gossip protocols, distributed coordination - - `Akka.Persistence/` - Event sourcing, snapshots, journals - - `Akka.Streams/` - Reactive streams with backpressure - - `Akka.TestKit/` - Testing utilities for actor systems - -- **`/src/contrib/`** - Contributed modules (DI integrations, serializers, cluster extensions) -- **`/src/benchmark/`** - Performance benchmarks using BenchmarkDotNet -- **`/src/examples/`** - Sample applications demonstrating patterns - -### Key Architectural Concepts -- **Actor Model**: Message-driven, hierarchical supervision, location transparency -- **Fault Tolerance**: Supervision strategies, let-it-crash philosophy -- **Distribution**: Remote actors, clustering, sharding -- **Reactive Streams**: Backpressure-aware stream processing -- **Event Sourcing**: Persistence with journals and snapshots - -### Testing Patterns -- Inherit from `AkkaSpec` or use `TestKit` for actor tests -- Use `TestProbe` for creating lightweight test actors -- Use `EventFilter` for asserting log messages -- Pass `ITestOutputHelper output` to test constructors for debugging -- Multi-node tests use separate projects (*.Tests.MultiNode.csproj) - -## Code Style and Conventions - -### C# Style -- Allman style braces (opening brace on new line) -- 4 spaces indentation, no tabs -- Private fields prefixed with underscore `_fieldName` -- Use `var` when type is apparent -- Default to `sealed` classes and records -- Enable `#nullable enable` in new/modified files -- Never use `async void`, `.Result`, or `.Wait()` -- Always pass `CancellationToken` through async call chains - -### API Design -- Maintain compatibility with JVM Akka while being .NET idiomatic -- Use `Task` instead of Future, `TimeSpan` instead of Duration -- Extend-only design - don't modify existing public APIs -- Preserve wire format compatibility for serialization -- Include unit tests with all changes - -### Test Naming -- Use `DisplayName` attribute for descriptive test names -- Follow pattern: `Should_ExpectedBehavior_When_Condition` - -## Development Workflow - -### Git Branches -- **`dev`** - Main development branch (default for PRs) -- **`v1.4`**, **`v1.3`**, etc. - Version maintenance branches for older releases -- Feature branches: `feature/description` -- Bugfix branches: `fix/description` - -### Making Changes -1. Always read existing code patterns in the module you're modifying -2. Follow existing conventions for that specific module -3. Add/update tests for your changes -4. Run incremental tests before committing -5. Ensure API compatibility tests pass for core changes -6. If the change is breaking, record it in `BREAKING_CHANGES_V1.6.md` in the same change (see below) - -### Tracking Breaking Changes (v1.6 cycle) -Until a stable **v1.6.0** ships, **every** change that goes into the `dev` branch and -introduces a **breaking behavior, wire-format, or public-API change** MUST be documented in -[`BREAKING_CHANGES_V1.6.md`](BREAKING_CHANGES_V1.6.md) (repo root), in the **same PR** that -makes the change. Use the entry format described in that file (status, component, type, -change, migration). This ledger is retired once `v1.6.0` is released, when its contents are -folded into the release notes / upgrade guide. - -### Target Frameworks -- **.NET 8.0** - Primary target -- **.NET 6.0** - Library compatibility -- **.NET Framework 4.8** - Legacy support -- **.NET Standard 2.0** - Library compatibility - -## Important Files -- `Directory.Build.props` - MSBuild properties, package versions -- `global.json` - .NET SDK version (8.0.403) -- `xunit.runner.json` - Test configuration (60s timeout, no parallelization) -- `.incrementalist/*.json` - Incremental build configurations -- `RELEASE_NOTES.md` - Version history and changelog \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file