# Batch 17 (Client Core second half) Implementation Plan > **For Codex:** REQUIRED SUB-SKILL: Use `executeplan` to implement this plan task-by-task. **Goal:** Implement and verify Batch 17 (`server/client.go` second half) across 60 client-core features and 9 tracked tests using evidence-backed, anti-stub execution gates. **Architecture:** Execute in three vertical feature groups (20 each) aligned to `client.go` functional seams: subscription/delivery, inbound/header/service import, and lifecycle/account/TLS/logging. Implement in `ClientConnection` partial files plus `ClientTypes` for `ClientInfo` behavior, then run tracked-test attempts with explicit dependency checks and defer reasoning where infra is still missing. **Tech Stack:** .NET 10, C# latest, xUnit 3, Shouldly, NSubstitute, PortTracker CLI, SQLite (`porting.db`) **Design doc:** `docs/plans/2026-02-27-batch-17-client-core-second-half-design.md` --- I'm using `writeplan` to create the implementation plan. ## Batch Inputs - Batch: `17` (`Client Core second half`) - Depends on: `16` - Features: `60` - Tests: `9` - Go source focus: `golang/nats-server/server/client.go` (line ~3057+) Feature groups (max ~20 each): - **Group A (20):** `477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496` - **Group B (20):** `497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,520` - **Group C (20):** `521,522,534,535,537,540,541,542,543,544,545,546,547,548,553,565,566,567,568,569` Tracked tests: - `528,545,552,553,568,598,2053,2057,2901` --- ## MANDATORY VERIFICATION PROTOCOL > **NON-NEGOTIABLE:** Every feature/test update in this batch must pass this protocol before status promotion. ### Per-Feature Verification Loop (REQUIRED for every feature ID) 1. Read tracker mapping and Go location: ```bash dotnet run --project tools/NatsNet.PortTracker -- feature show --db porting.db ``` 2. Read the exact Go function in `golang/nats-server/server/client.go`. 3. Write minimal behavior-faithful C# implementation in mapped .NET file. 4. Build: ```bash dotnet build dotnet/ ``` 5. Run focused related tests (class/method filter): ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~" --verbosity normal ``` 6. Confirm non-zero executed tests and `Failed: 0`. 7. Add feature ID to verified-candidate list only after green build + green related tests. ### Per-Test Verification Loop (REQUIRED for every tracked test ID) 1. Read mapping + dependencies: ```bash dotnet run --project tools/NatsNet.PortTracker -- test show --db porting.db ``` 2. Read referenced Go test in `server/filestore_test.go`, `server/memstore_test.go`, or `server/server_test.go`. 3. Port behavior intent with real Arrange/Act/Assert. 4. Run the single mapped test: ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~." --verbosity normal ``` 5. Only mark `verified` when test executes and passes (`Passed: 1`, `Failed: 0`). ### Stub Detection Check (REQUIRED after every feature group and test task) Run stub scans before any `complete`/`verified` updates: ```bash # Feature code stubs/placeholders grep -R -n -E "NotImplementedException|TODO|PLACEHOLDER" \ dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection*.cs \ dotnet/src/ZB.MOM.NatsNet.Server/ClientTypes.cs # Empty method bodies in touched feature files grep -R -n -E "^[[:space:]]*(public|internal|private|protected)[^{;]*\\)[[:space:]]*\\{[[:space:]]*\\}$" \ dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection*.cs \ dotnet/src/ZB.MOM.NatsNet.Server/ClientTypes.cs # Test stubs/placeholders grep -R -n -E "NotImplementedException|Assert\\.True\\(true\\)|Assert\\.Pass|ShouldBe\\(true\\);|// TODO|// PLACEHOLDER" \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests ``` Any new hit in touched files blocks promotion until fixed or deferred with explicit reason. ### Build Gate (REQUIRED after each feature group) After every feature group task: ```bash dotnet build dotnet/ ``` Required: `0` build errors. ### Test Gate (REQUIRED before marking features `verified`) Before any feature IDs move to `verified`, run and pass all related suites: ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ClientConnectionStubFeaturesTests" --verbosity normal dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ClientTests" --verbosity normal dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ProtocolParserTests" --verbosity normal ``` If a group touches rate-limit logging or mapped server behaviors, also run: ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~NatsServerTests" --verbosity normal ``` Required: `Failed: 0` and non-zero executed tests for changed scenarios. ### Status Update Protocol (REQUIRED, evidence-backed) 1. Maximum **15 IDs per `feature batch-update` / `test batch-update` call**. 2. Allowed flow: - Features: `deferred -> stub -> complete -> verified` (or `deferred` with reason) - Tests: `deferred -> stub -> verified` (or `deferred` with reason) 3. Evidence required for each update chunk: - Go source review completed - Build output green - Related test output green - Stub scan clean 4. If audit disagrees, use explicit override reason. ### Checkpoint Protocol Between Tasks (REQUIRED) After each major task (Group A, Group B, Group C, tests): 1. Full build: ```bash dotnet build dotnet/ ``` 2. Full unit test run: ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal ``` 3. Confirm no new regressions. 4. Commit checkpoint before starting the next task. --- ## ANTI-STUB GUARDRAILS (NON-NEGOTIABLE) ### Forbidden Patterns Do not introduce or keep these in Batch 17 feature/test code: - `throw new NotImplementedException(...)` - `// TODO` or `// PLACEHOLDER` in executable Batch 17 paths - Empty method body placeholders (`{ }`) - Trivial pass tests (`Assert.True(true)`, `Assert.Pass()`, literal-only assertions) - Constant return placeholders for behavior-heavy methods (for example always `true`/`false` without Go-equivalent logic) - Fake wrappers that ignore inputs and bypass Go behavior intent ### Hard Limits - Max ~20 feature IDs per implementation task group (fixed at 20/20/20) - Max 15 IDs per status-update command - No status promotion without stub scan + build gate + test gate evidence - No cross-group promotion; complete verification for one group before starting next - Mandatory checkpoint commit between task groups ### If You Get Stuck 1. Stop work on the blocked item immediately. 2. Do **not** stub or fake-pass. 3. Set item back to `deferred` with exact blocker reason: ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature update --status deferred --db porting.db \ --override "blocked: " ``` or ```bash dotnet run --project tools/NatsNet.PortTracker -- \ test update --status deferred --db porting.db \ --override "blocked: " ``` 4. Continue with the next unblocked ID in the same task. --- ### Task 1: Preflight and Batch Start **Files:** - Modify: `porting.db` **Step 1: Confirm dependency readiness** ```bash dotnet run --project tools/NatsNet.PortTracker -- batch show 17 --db porting.db dotnet run --project tools/NatsNet.PortTracker -- batch ready --db porting.db ``` Expected: Batch 17 is ready (Batch 16 complete). **Step 2: Start batch** ```bash dotnet run --project tools/NatsNet.PortTracker -- batch start 17 --db porting.db ``` **Step 3: Stage Group A to `stub` (<=15 IDs per command)** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "477,478,479,480,481,482,483,484,485,486,487,488,489,490,491" \ --set-status stub --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "492,493,494,495,496" \ --set-status stub --db porting.db --execute ``` **Step 4: Commit preflight** ```bash git add porting.db git commit -m "chore(batch17): start batch and stage group-a ids" ``` ### Task 2: Group A Features (20) - Subscriptions, Delivery, Pub/Reply Permissions **Feature IDs:** `477-496` **Files:** - Create: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.SubscriptionsAndDelivery.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ClientConnectionStubFeaturesTests.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ClientTests.cs` **Step 1: Write/extend failing tests for Group A behavior** Focus on: - shadow subscription additions - unsubscribe + deny-sub checks - route/leaf header generation - delivery/pruning/reply tracking behavior - publish allow checks and reply classifiers **Step 2: Run focused tests and confirm failures** ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ClientConnectionStubFeaturesTests" --verbosity normal dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ClientTests" --verbosity normal ``` **Step 3: Implement Group A methods using per-feature verification loop** **Step 4: Run mandatory stub detection + build gate + test gate** Use protocol commands above. **Step 5: Promote Group A feature statuses** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "477,478,479,480,481,482,483,484,485,486,487,488,489,490,491" \ --set-status complete --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "492,493,494,495,496" \ --set-status complete --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "477,478,479,480,481,482,483,484,485,486,487,488,489,490,491" \ --set-status verified --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "492,493,494,495,496" \ --set-status verified --db porting.db --execute ``` **Step 6: Checkpoint protocol + commit** ```bash git add dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.SubscriptionsAndDelivery.cs \ dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ClientConnectionStubFeaturesTests.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ClientTests.cs \ porting.db git commit -m "feat(batch17): port subscription and delivery client core features" ``` ### Task 3: Group B Features (20) - Inbound Pipeline, Headers, Service Imports, Msg Results **Feature IDs:** `497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,520` **Files:** - Create: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.InboundAndHeaders.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ClientConnectionStubFeaturesTests.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Protocol/ProtocolParserTests.cs` **Step 1: Write/extend failing tests for Group B behavior** Focus on: - inbound client message processing and mapped subject selection - gateway reply map + response service import setup - header remove/set/get/slice helpers - `processServiceImport`, route-target updates, and `processMsgResults` - ping timer behavior (`processPingTimer`) **Step 2: Run focused tests and confirm failures** ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ClientConnectionStubFeaturesTests" --verbosity normal dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ProtocolParserTests" --verbosity normal ``` **Step 3: Implement Group B methods using per-feature verification loop** **Step 4: Run mandatory stub detection + build gate + test gate** **Step 5: Promote Group B feature statuses (<=15 IDs/chunk)** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "497,498,499,500,501,502,503,504,505,506,507,508,509,510,511" \ --set-status complete --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "512,513,514,515,520" \ --set-status complete --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "497,498,499,500,501,502,503,504,505,506,507,508,509,510,511" \ --set-status verified --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "512,513,514,515,520" \ --set-status verified --db porting.db --execute ``` **Step 6: Checkpoint protocol + commit** ```bash git add dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.InboundAndHeaders.cs \ dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ClientConnectionStubFeaturesTests.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Protocol/ProtocolParserTests.cs \ porting.db git commit -m "feat(batch17): port inbound, header, and service-import client features" ``` ### Task 4: Group C Features (20) - Lifecycle, Account/Info, TLS, Rate-Limit Logging **Feature IDs:** `521,522,534,535,537,540,541,542,543,544,545,546,547,548,553,565,566,567,568,569` **Files:** - Create: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.LifecycleAndTls.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ClientTypes.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ClientConnectionStubFeaturesTests.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsServerTests.Impltests.cs` **Step 1: Write/extend failing tests for Group C behavior** Focus on: - ping interval adjust + stale watcher + first ping timer - account cache helpers and reload/reconnect paths - client info account/service account enrichment - TLS handshake wrappers and failure behavior - rate-limited error/warn/debug logging wrappers **Step 2: Run focused tests and confirm failures** ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ClientConnectionStubFeaturesTests" --verbosity normal dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~NatsServerTests" --verbosity normal ``` **Step 3: Implement Group C methods using per-feature verification loop** **Step 4: Run mandatory stub detection + build gate + test gate** **Step 5: Promote Group C feature statuses (<=15 IDs/chunk)** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "521,522,534,535,537,540,541,542,543,544,545,546,547,548,553" \ --set-status complete --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "565,566,567,568,569" \ --set-status complete --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "521,522,534,535,537,540,541,542,543,544,545,546,547,548,553" \ --set-status verified --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "565,566,567,568,569" \ --set-status verified --db porting.db --execute ``` **Step 6: Checkpoint protocol + commit** ```bash git add dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.LifecycleAndTls.cs \ dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs \ dotnet/src/ZB.MOM.NatsNet.Server/ClientTypes.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ClientConnectionStubFeaturesTests.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsServerTests.Impltests.cs \ porting.db git commit -m "feat(batch17): port lifecycle, tls, and rate-limited logging features" ``` ### Task 5: Tracked Tests (9) - Implement or Explicitly Defer With Reason **Test IDs:** `528,545,552,553,568,598,2053,2057,2901` **Files:** - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreTests.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamMemoryStoreTests.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsServerTests.Impltests.cs` - Modify: `porting.db` **Step 1: Stage all 9 tests to `stub` (single chunk <=15)** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "528,545,552,553,568,598,2053,2057,2901" \ --set-status stub --db porting.db --execute ``` **Step 2: For each test, run dependency readiness check** If dependencies remain deferred outside Batch 17, do not force-port; defer with explicit blocker. **Step 3: Port only implementable tests using per-test verification loop** Run each mapped test individually and confirm it executes/passes. **Step 4: Stub scan + build + targeted JetStream/Server test gates** ```bash dotnet build dotnet/ dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStreamFileStoreTests" --verbosity normal dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStreamMemoryStoreTests" --verbosity normal dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~NatsServerTests" --verbosity normal ``` **Step 5: Update statuses** - Verified chunk (only those with direct pass evidence, <=15 IDs). - Deferred updates for blocked tests with explicit `--override` reason. **Step 6: Checkpoint protocol + commit** ```bash git add dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreTests.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamMemoryStoreTests.cs \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsServerTests.Impltests.cs \ porting.db git commit -m "test(batch17): resolve tracked tests with pass evidence or explicit deferrals" ``` ### Task 6: Final Batch 17 Verification and Closure **Files:** - Modify: `porting.db` - Generate: `reports/current.md` **Step 1: Full verification sweep** ```bash dotnet build dotnet/ dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal dotnet run --project tools/NatsNet.PortTracker -- batch show 17 --db porting.db ``` **Step 2: Enforce no remaining Batch 17 stubs** No Batch 17 feature/test should remain in `stub` status. **Step 3: Complete batch** ```bash dotnet run --project tools/NatsNet.PortTracker -- batch complete 17 --db porting.db ``` **Step 4: Update report + final commit** ```bash ./reports/generate-report.sh git add porting.db reports/current.md reports/ git commit -m "chore(batch17): complete client core second-half verification cycle" ```