229 lines
7.4 KiB
Markdown
229 lines
7.4 KiB
Markdown
# AGENTS.md
|
|
|
|
## Project Summary
|
|
|
|
This project ports the NATS messaging server from Go to .NET 10 C#. The Go source (~130K LOC) is the reference at `golang/nats-server/`. Porting progress is tracked in an SQLite database (`porting.db`) managed by the PortTracker CLI tool.
|
|
|
|
## Folder Layout
|
|
|
|
```
|
|
natsnet/
|
|
├── golang/nats-server/ # Go source (read-only reference)
|
|
├── dotnet/
|
|
│ ├── src/ZB.MOM.NatsNet.Server/ # Main server library
|
|
│ ├── src/ZB.MOM.NatsNet.Server.Host/ # Host entry point
|
|
│ └── tests/
|
|
│ ├── ZB.MOM.NatsNet.Server.Tests/ # Unit tests
|
|
│ └── ZB.MOM.NatsNet.Server.IntegrationTests/ # Integration tests
|
|
├── tools/NatsNet.PortTracker/ # CLI tracking tool
|
|
├── docs/standards/dotnet-standards.md # .NET coding standards (MUST follow)
|
|
├── docs/plans/phases/ # Phase instruction guides
|
|
├── reports/current.md # Latest porting status
|
|
├── porting.db # SQLite tracking database
|
|
└── porting-schema.sql # Database schema
|
|
```
|
|
|
|
## Build and Test
|
|
|
|
```bash
|
|
# Build the solution
|
|
dotnet build dotnet/
|
|
|
|
# Run all unit tests
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
|
|
# Run filtered tests (by namespace/class)
|
|
dotnet test --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.Protocol" \
|
|
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
|
|
# Run integration tests
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.IntegrationTests/
|
|
|
|
# Generate porting report
|
|
./reports/generate-report.sh
|
|
```
|
|
|
|
## .NET Coding Standards
|
|
|
|
**MUST follow all rules in `docs/standards/dotnet-standards.md`.**
|
|
|
|
Critical rules (non-negotiable):
|
|
|
|
- .NET 10, C# latest, nullable enabled
|
|
- **xUnit 3** + **Shouldly** + **NSubstitute** for testing
|
|
- **NEVER use FluentAssertions or Moq** — these are forbidden
|
|
- PascalCase for public members, `_camelCase` for private fields
|
|
- File-scoped namespaces: `ZB.MOM.NatsNet.Server.[Module]`
|
|
- Use `CancellationToken` on all async signatures
|
|
- Use `ReadOnlySpan<byte>` on hot paths
|
|
- Test naming: `[Method]_[Scenario]_[Expected]`
|
|
- Test class naming: `[ClassName]Tests`
|
|
- Structured logging with `ILogger<T>` and `LogContext.PushProperty`
|
|
|
|
## PortTracker CLI
|
|
|
|
All tracking commands use this base:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- <command> --db porting.db
|
|
```
|
|
|
|
### Querying
|
|
|
|
| Command | Purpose |
|
|
|---------|---------|
|
|
| `report summary` | Show overall porting progress |
|
|
| `dependency ready` | List items ready to port (no unported deps) |
|
|
| `dependency blocked` | List items blocked by unported deps |
|
|
| `feature list --status <s>` | List features by status |
|
|
| `feature list --module <id>` | List features in a module |
|
|
| `feature show <id>` | Show feature details (Go source path, .NET target) |
|
|
| `test list --status <s>` | List tests by status |
|
|
| `test show <id>` | Show test details |
|
|
| `module list` | List all modules |
|
|
| `module show <id>` | Show module with its features and tests |
|
|
|
|
### Updating Status
|
|
|
|
| Command | Purpose |
|
|
|---------|---------|
|
|
| `feature update <id> --status <s>` | Update one feature |
|
|
| `feature batch-update --ids "1-10" --set-status <s> --execute` | Bulk update features |
|
|
| `test update <id> --status <s>` | Update one test |
|
|
| `test batch-update --ids "1-10" --set-status <s> --execute` | Bulk update tests |
|
|
| `module update <id> --status <s>` | Update module status |
|
|
|
|
### Audit Verification
|
|
|
|
Status updates are verified against Roslyn audit results. If the audit disagrees with your requested status, add `--override "reason"` to force it.
|
|
|
|
```bash
|
|
feature update 42 --status verified --override "manually verified logic"
|
|
```
|
|
|
|
### Audit Commands
|
|
|
|
| Command | Purpose |
|
|
|---------|---------|
|
|
| `audit --type features` | Dry-run audit of features against .NET source |
|
|
| `audit --type tests` | Dry-run audit of tests against test project |
|
|
| `audit --type features --execute` | Apply audit classifications to DB |
|
|
| `audit --type tests --execute` | Apply test audit classifications to DB |
|
|
|
|
### Valid Statuses
|
|
|
|
```
|
|
not_started → stub → complete → verified
|
|
└→ n_a (not applicable)
|
|
└→ deferred (blocked, needs server infra)
|
|
```
|
|
|
|
### Batch ID Syntax
|
|
|
|
`--ids` accepts: ranges `"100-200"`, lists `"1,5,10"`, or mixed `"1-5,10,20-25"`.
|
|
|
|
All batch commands default to dry-run. Add `--execute` to apply.
|
|
|
|
## Porting Workflow
|
|
|
|
### Finding Work
|
|
|
|
1. Query for features ready to port:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- dependency ready --db porting.db
|
|
```
|
|
|
|
2. Or find deferred/stub features in a specific module:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature list --module <id> --status deferred --db porting.db
|
|
```
|
|
|
|
3. To find tests that need implementing:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- test list --status stub --db porting.db
|
|
dotnet run --project tools/NatsNet.PortTracker -- test list --status deferred --db porting.db
|
|
```
|
|
|
|
### Implementing a Feature
|
|
|
|
1. **Claim it** — mark as stub before starting:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature update <id> --status stub --db porting.db
|
|
```
|
|
|
|
2. **Read the Go source** — use `feature show <id>` to get the Go file path and line numbers, then read the Go implementation.
|
|
|
|
3. **Write idiomatic C#** — translate intent, not lines:
|
|
- Use `async`/`await`, not goroutine translations
|
|
- Use `Channel<T>` for Go channels
|
|
- Use `CancellationToken` for `context.Context`
|
|
- Use `ReadOnlySpan<byte>` on hot paths
|
|
- Use `Lock` (C# 13) for `sync.Mutex`
|
|
- Use `ReaderWriterLockSlim` for `sync.RWMutex`
|
|
|
|
4. **Ensure it compiles** — run `dotnet build dotnet/`
|
|
|
|
5. **Mark complete**:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature update <id> --status complete --db porting.db
|
|
```
|
|
|
|
### Implementing a Unit Test
|
|
|
|
1. **Read the Go test** — use `test show <id>` to get Go source location.
|
|
2. **Read the corresponding .NET feature** to understand the API surface.
|
|
3. **Write the test** in `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/` using xUnit 3 + Shouldly + NSubstitute.
|
|
4. **Run it**:
|
|
|
|
```bash
|
|
dotnet test --filter "FullyQualifiedName~TestClassName" \
|
|
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
```
|
|
|
|
5. **Mark verified** (if passing):
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- test update <id> --status verified --db porting.db
|
|
```
|
|
|
|
### After Completing Work
|
|
|
|
1. Run affected tests to verify nothing broke.
|
|
2. Update DB status for all items you changed.
|
|
3. Check what's newly unblocked:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- dependency ready --db porting.db
|
|
```
|
|
|
|
4. Generate updated report:
|
|
|
|
```bash
|
|
./reports/generate-report.sh
|
|
```
|
|
|
|
## Go to .NET Translation Reference
|
|
|
|
| Go Pattern | .NET Equivalent |
|
|
|------------|-----------------|
|
|
| `goroutine` | `Task.Run` or `async`/`await` |
|
|
| `chan T` | `Channel<T>` |
|
|
| `select` | `Task.WhenAny` |
|
|
| `sync.Mutex` | `Lock` (C# 13) |
|
|
| `sync.RWMutex` | `ReaderWriterLockSlim` |
|
|
| `sync.WaitGroup` | `Task.WhenAll` or `CountdownEvent` |
|
|
| `atomic.Int64` | `Interlocked` methods on `long` field |
|
|
| `context.Context` | `CancellationToken` |
|
|
| `defer` | `try`/`finally` or `using` |
|
|
| `error` return | Exceptions or Result pattern |
|
|
| `[]byte` | `byte[]`, `ReadOnlySpan<byte>`, `ReadOnlyMemory<byte>` |
|
|
| `map[K]V` | `Dictionary<K,V>` or `ConcurrentDictionary<K,V>` |
|
|
| `interface{}` | `object` or generics |
|
|
| `time.Duration` | `TimeSpan` |
|
|
| `weak.Pointer[T]` | `WeakReference<T>` |
|