# Batch 3 (SendQ, Service, Client ProxyProto) Implementation Plan > **For Codex:** REQUIRED SUB-SKILL: Use `executeplan` to implement this plan task-by-task. **Goal:** Implement and verify Batch 3’s 18 features and 1 tracked test with Go-parity behavior, zero stub leakage, and evidence-backed PortTracker status updates. **Architecture:** Execute Batch 3 in three feature groups (ProxyProto, SendQueue, Service) plus one tracked-test group. Reuse existing .NET proxy/service behavior where valid, add compatibility surfaces for mapped Batch 3 methods, and run strict per-feature verification loops before any status promotion. **Tech Stack:** .NET 10, C# latest, xUnit 3, Shouldly, NSubstitute, PortTracker CLI, SQLite (`porting.db`) **Design doc:** `docs/plans/2026-02-27-batch-3-sendq-service-client-proxyproto-design.md` --- ## Batch 3 Working Set Feature groups (max group size <= 20 features): - **Group A - ProxyProto (8):** `574`, `575`, `576`, `577`, `578`, `579`, `580`, `581` - **Group B - SendQueue (3):** `2971`, `2972`, `2973` - **Group C - Service (7):** `3148`, `3149`, `3150`, `3151`, `3152`, `3153`, `3154` - **Tracked test (1):** `2832` Batch facts: - Total features: `18` - Total tracked tests: `1` - Dependency: `Batch 1` - Go files: `server/client_proxyproto.go`, `server/sendq.go`, `server/service.go`, `server/service_windows.go` > `dotnet` is not on PATH in this environment. Use `/usr/local/share/dotnet/dotnet` in all commands. --- ## MANDATORY VERIFICATION PROTOCOL > **NON-NEGOTIABLE:** Every feature and test in this plan must follow this protocol. Skipping steps is a plan violation. ### What Counts as Real Verification A feature or test can be marked `verified` only if all are true: 1. Go source was reviewed for the mapped ID (`feature show` or `test show` + source lines). 2. C# implementation/test contains real behavior (no placeholders/fake pass assertions). 3. Related tests execute with non-zero discovery and pass. 4. Group build gate is green. 5. Stub detection checks are clean for touched files. ### Per-Feature Verification Loop (REQUIRED for every feature ID) 1. Read mapped Go source and intent: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- feature show --db porting.db ``` 2. Write/adjust C# implementation in mapped target area. 3. Build immediately after feature-level change: ```bash /usr/local/share/dotnet/dotnet build dotnet/ ``` 4. Run related tests for that feature area. 5. Confirm `Passed > 0` and `Failed = 0` before adding ID to verified candidates. ### Per-Test Verification Loop (REQUIRED for test `2832`) 1. Read Go test source and dependent feature behavior: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- test show 2832 --db porting.db ``` 2. Write the C# test first (real Arrange/Act/Assert, no placeholder asserts). 3. Run the specific test filter and confirm it is discovered and passing. 4. Run containing class filter and confirm cumulative pass summary. ### Stub Detection Check (REQUIRED after each feature group and test group) Run on touched files before any status updates: ```bash # Forbidden markers in changed source/test files git diff -- dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests | \ grep -nE "^\+.*(NotImplementedException|TODO|PLACEHOLDER|Assert\.True\(true\)|Assert\.Pass\(|ShouldBe\(true\);)" # Empty method bodies introduced in touched files for f in $(git diff --name-only -- dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests | grep -E "\.cs$"); do grep -nE "(public|private|internal|protected).*\)\s*\{\s*\}" "$f"; done ``` Any match blocks status promotion until fixed or reclassified (`deferred`/`n_a`) with reason. ### Build Gate (REQUIRED after each feature group) ```bash /usr/local/share/dotnet/dotnet build dotnet/ ``` Required: `0` errors. ### Test Gate (REQUIRED before marking features `verified`) All related tests for the active group must pass: - Group A (ProxyProto): ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.Protocol.ProxyProtocolTests" --verbosity normal ``` - Group B (SendQueue): ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~SendQueueTests" --verbosity normal ``` - Group C (Service): ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~SignalHandlerTests|FullyQualifiedName~ServiceManagerTests" --verbosity normal ``` - Group D (tracked test): ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~RoutePoolRouteStoredSameIndexBothSides_ShouldSucceed" --verbosity normal ``` ### Status Update Protocol - **Maximum 15 IDs per `batch-update` call** (hard cap). - Do not mark `verified` without evidence bundle (Go source reference, build output, related test output, stub-scan output). - Apply status in order: `deferred/not_started -> stub -> complete -> verified`. - Use `n_a` only with explicit technical justification. Examples: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status stub --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status complete --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status verified --db porting.db --execute ``` For blocked items: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature update --status deferred --db porting.db --override "blocked: " /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature update --status n_a --db porting.db --override "n/a: " ``` ### Checkpoint Protocol Between Tasks (REQUIRED) After each task group and before starting the next: 1. Full build: ```bash /usr/local/share/dotnet/dotnet build dotnet/ ``` 2. Full unit tests: ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal ``` 3. Confirm no regressions introduced. 4. Commit task-scoped changes (including `porting.db`) before proceeding. --- ## ANTI-STUB GUARDRAILS (NON-NEGOTIABLE) ### Forbidden Patterns These are forbidden in feature or test changes for Batch 3: - `throw new NotImplementedException()` - `TODO` / `PLACEHOLDER` markers in newly added code - Empty method body placeholders (`{ }`) for mapped features - Fake pass assertions (`Assert.True(true)`, `Assert.Pass()`, meaningless sentinel assertions) - Default/null return used only to satisfy compiler with no Go-equivalent behavior - Test methods with no production call + no meaningful assertion ### Hard Limits - Max `15` IDs per status update command. - Max `1` feature group promoted per verification cycle. - Mandatory `build` + related `test` gate before `verified`. - Mandatory stub scan before every status promotion. - Mandatory checkpoint commit between groups. ### If You Get Stuck (REQUIRED behavior) Do not stub and do not fake-pass. 1. Keep item as `deferred` (or `n_a` only if genuinely non-applicable). 2. Add explicit reason with `--override` in PortTracker. 3. Commit only proven work. 4. Continue with next unblocked ID. --- ### Task 1: Group A - Proxy Protocol Features (`574-581`) **Files:** - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs` - Create: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.ProxyProto.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ProxyProtocol.cs` - Modify/Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Protocol/ProxyProtocolTests.cs` **Step 1: Mark Group A features as `stub`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status stub --db porting.db --execute ``` **Step 2: Write/adjust failing tests first** Add coverage for any missing mapped behavior: - `RemoteAddr` mapped semantics - version detect wrappers - v1/v2 parser wrapper entry points - IPv4/IPv6 parse wrappers **Step 3: Run focused ProxyProto tests (expect fail first, then pass)** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~ProxyProtocolTests" --verbosity normal ``` **Step 4: Implement minimal production parity** - Add `ClientConnection` mapped method shims to existing parser core. - Keep parsing logic centralized in `Protocol/ProxyProtocol.cs`. **Step 5: Re-run focused tests until green** Use Step 3 command. **Step 6: Run stub detection + build gate** Run protocol checks. **Step 7: Promote statuses (`complete`, then `verified`)** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status complete --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status verified --db porting.db --execute ``` **Step 8: Checkpoint protocol + commit** ```bash git add dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs \ dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.ProxyProto.cs \ dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ProxyProtocol.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Protocol/ProxyProtocolTests.cs \ porting.db git commit -m "feat(batch3): verify client proxy protocol feature group" ``` --- ### Task 2: Group B - SendQueue Features (`2971-2973`) **Files:** - Create: `dotnet/src/ZB.MOM.NatsNet.Server/SendQueue.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Accounts.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Accounts/Account.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs` - Create/Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/SendQueueTests.cs` **Step 1: Mark Group B features as `stub`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2971,2972,2973" --set-status stub --db porting.db --execute ``` **Step 2: Write failing tests first** Cover at minimum: - `NewSendQ` creates queue and starts loop entry path - `Send` no-ops when queue is null/disposed - queued messages are copied and passed to internal client path **Step 3: Run focused SendQueue tests (expect fail first, then pass)** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~SendQueueTests" --verbosity normal ``` **Step 4: Implement minimal SendQueue parity** - Port `newSendQ`, `internalLoop`, `send` intent using `IpQueue` + existing internal client APIs. - Replace `Account.SendQueue` placeholder with concrete type usage. **Step 5: Re-run focused tests until green** Use Step 3 command. **Step 6: Run stub detection + build gate** Run protocol checks. **Step 7: Promote statuses (`complete`, then `verified`)** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2971,2972,2973" --set-status complete --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2971,2972,2973" --set-status verified --db porting.db --execute ``` **Step 8: Checkpoint protocol + commit** ```bash git add dotnet/src/ZB.MOM.NatsNet.Server/SendQueue.cs \ dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Accounts.cs \ dotnet/src/ZB.MOM.NatsNet.Server/Accounts/Account.cs \ dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/SendQueueTests.cs \ porting.db git commit -m "feat(batch3): implement send queue feature group" ``` --- ### Task 3: Group C - Service Features (`3148-3154`) **Files:** - Create: `dotnet/src/ZB.MOM.NatsNet.Server/Internal/ServiceManager.cs` - Create (if needed): `dotnet/src/ZB.MOM.NatsNet.Server/Internal/ServiceManager.Windows.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Internal/SignalHandler.cs` - Create/Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/ServiceManagerTests.cs` - Modify/Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/SignalHandlerTests.cs` **Step 1: Mark Group C features as `stub`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "3148,3149,3150,3151,3152,3153,3154" --set-status stub --db porting.db --execute ``` **Step 2: Write failing tests first** Cover: - non-Windows `Run` behavior - non-Windows `IsWindowsService` behavior - service-name configuration behavior (if implemented) - Windows-only hooks either behaviorally verified or explicitly marked `n_a` **Step 3: Run focused service tests (expect fail first, then pass)** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~SignalHandlerTests|FullyQualifiedName~ServiceManagerTests" --verbosity normal ``` **Step 4: Implement service parity layer** - Add `ServiceManager` mapped surface. - For Windows-only features (`3150-3154`), choose one per-ID outcome based on evidence: - implemented wrapper (`complete/verified`), or - `n_a` with explicit reason tied to host-level WindowsService ownership. **Step 5: Re-run focused tests until green** Use Step 3 command. **Step 6: Run stub detection + build gate** Run protocol checks. **Step 7: Promote statuses with evidence** - Use `complete` -> `verified` for implemented service features. - Use `n_a` for validated non-applicable Windows-host-only entries. - Keep max 7 IDs in this task update (below 15 cap). **Step 8: Checkpoint protocol + commit** ```bash git add dotnet/src/ZB.MOM.NatsNet.Server/Internal/ServiceManager.cs \ dotnet/src/ZB.MOM.NatsNet.Server/Internal/ServiceManager.Windows.cs \ dotnet/src/ZB.MOM.NatsNet.Server/Internal/SignalHandler.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/ServiceManagerTests.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/SignalHandlerTests.cs \ porting.db git commit -m "feat(batch3): implement service feature group" ``` --- ### Task 4: Group D - Tracked Test `2832` **Files:** - Modify/Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs` - Modify (only if required by real behavior): `dotnet/src/ZB.MOM.NatsNet.Server/Routes/*` **Step 1: Mark test `2832` as `stub`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test update 2832 --status stub --db porting.db ``` **Step 2: Write real failing test first** Implement `RoutePoolRouteStoredSameIndexBothSides_ShouldSucceed` with actual route index/endpoint assertions mirroring Go intent. **Step 3: Run focused test and class gates** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~RoutePoolRouteStoredSameIndexBothSides_ShouldSucceed" --verbosity normal /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~RouteHandlerTests" --verbosity normal ``` **Step 4: If infrastructure is missing, defer explicitly (do not stub)** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test update 2832 --status deferred --db porting.db \ --override "blocked: requires route-pool runtime topology not yet implemented in current server core" ``` **Step 5: If test is green, promote to `verified`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test update 2832 --status verified --db porting.db ``` **Step 6: Checkpoint protocol + commit** ```bash git add dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs \ dotnet/src/ZB.MOM.NatsNet.Server/Routes \ porting.db git commit -m "test(batch3): handle route pool same-index test" ``` --- ### Task 5: Batch 3 Closure **Files:** - Modify: `porting.db` - Generate: `reports/current.md` (via report script) **Step 1: Verify batch state** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 3 --db porting.db ``` Required: all 18 features and test `2832` are `verified`/`complete`/`n_a`; unresolved blockers remain explicitly `deferred` with reason. **Step 2: Full regression gate** ```bash /usr/local/share/dotnet/dotnet build dotnet/ /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal ``` Required: `Failed: 0` for full unit test suite. **Step 3: Complete batch if eligible** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch complete 3 --db porting.db ``` **Step 4: Validate summary + readiness** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- dependency ready --db porting.db ``` **Step 5: Generate report and final commit** ```bash ./reports/generate-report.sh git add porting.db reports/current.md git commit -m "chore(batch3): close sendq-service-proxyproto batch" ```