# Batch 29 JetStream Batching Implementation Plan > **For Codex:** REQUIRED SUB-SKILL: Use `executeplan` to implement this plan task-by-task. **Goal:** Port and verify Batch 29 JetStream batching behavior (12 features, 3 tests) from `server/jetstream_batching.go` and mapped `raft_test.go` cases without introducing stubs or unverifiable tracker updates. **Architecture:** Execute in two feature groups and one test group. Group A ports lifecycle/store primitives (`1508-1514`), Group B ports staged/apply/header checks (`1515-1519`, including the large `checkMsgHeadersPreClusteredProposal` surface), then mapped Raft tests are ported/verified. Every ID follows strict per-item evidence gates before 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-29-jetstream-batching-design.md` --- ## Batch 29 Scope - Batch ID: `29` - Name: `JetStream Batching` - Dependency: `27` - Go source: `golang/nats-server/server/jetstream_batching.go` - Features: `1508-1519` (12 total) - Tests: `2654,2674,2718` Primary implementation files: - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamBatching.cs` - Optional split (recommended for readability of feature `1519`): - Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamBatching.HeaderChecks.cs` - Optional supporting updates only if required by compile/runtime behavior: - `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.cs` - `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamTypes.cs` - `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs` Primary test files: - Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/RaftNodeTests.cs` - Modify or Create focused batching tests as needed: - `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamBatchingCoreTests.cs` - Existing deferred batching integration placeholders (do not convert to fake unit tests): - `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamBatchingTests.cs` --- ## MANDATORY VERIFICATION PROTOCOL > **NON-NEGOTIABLE:** Applies to every feature ID and test ID in Batch 29. ### Preflight Dependency Gate (REQUIRED before Task 1 coding) 1. Verify dependency and readiness: ```bash dotnet run --project tools/NatsNet.PortTracker -- batch show 27 --db porting.db dotnet run --project tools/NatsNet.PortTracker -- batch show 29 --db porting.db dotnet run --project tools/NatsNet.PortTracker -- batch ready --db porting.db ``` 2. Start the batch only when dependency checks pass: ```bash dotnet run --project tools/NatsNet.PortTracker -- batch start 29 --db porting.db ``` 3. Baseline gates: ```bash dotnet build dotnet/ dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ ``` ### Per-Feature Verification Loop (REQUIRED for each feature ID) For each feature in current task group: 1. Inspect mapping and Go span: ```bash dotnet run --project tools/NatsNet.PortTracker -- feature show --db porting.db sed -n ',p' golang/nats-server/server/jetstream_batching.go ``` 2. Mark that feature as `stub` before editing: ```bash dotnet run --project tools/NatsNet.PortTracker -- feature update --status stub --db porting.db ``` 3. Implement mapped behavior in .NET (no placeholders). 4. Run **Build Gate**. 5. Run **Test Gate** (focused tests for changed behavior). 6. Run **Stub Detection Check** on touched files. 7. If gates are green and no stubs are detected, promote feature to `complete`: ```bash dotnet run --project tools/NatsNet.PortTracker -- feature update --status complete --db porting.db ``` 8. Promote feature IDs to `verified` only after task-level checkpoint passes. ### Per-Test Verification Loop (REQUIRED for each test ID) 1. Inspect mapped test details and Go source: ```bash dotnet run --project tools/NatsNet.PortTracker -- test show --db porting.db sed -n ',p' golang/nats-server/server/raft_test.go ``` 2. Mark test `stub` before editing: ```bash dotnet run --project tools/NatsNet.PortTracker -- test update --status stub --db porting.db ``` 3. Implement real Arrange/Act/Assert test calling production code. 4. Run single-test command: ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.JetStream.RaftNodeTests." \ --verbosity normal ``` 5. Confirm summary includes `Passed: 1, Failed: 0` (not `Passed: 0`). 6. Run class-level test gate: ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.JetStream.RaftNodeTests" ``` 7. Run Stub Detection Check. 8. Promote test to `complete`, then `verified` at checkpoint when evidence is complete. ### Stub Detection Check (REQUIRED after every feature/test loop and each task) Run against touched code: ```bash git diff --name-only -- dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests \ | rg "\.cs$" \ | xargs rg -n "(NotImplementedException|// TODO|// PLACEHOLDER|Assert\\.True\\(true\\)|Assert\\.Pass|throw new Exception\\(\"TODO\"\\)|=>\\s*default;|=>\\s*null;)" ``` Any match in touched methods means the item is not eligible for `complete` or `verified`. ### Build Gate (REQUIRED) `dotnet build dotnet/` is mandatory: - after each feature implementation loop - after each test implementation loop - before any `batch-update` - at every task checkpoint ### Test Gate (REQUIRED) Minimum per-task gates: ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStreamBatching" dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~RaftNodeTests" ``` Checkpoint and final gates: ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ ``` ### Status Update Protocol (HARD LIMIT: max 15 IDs per batch-update) - Allowed path: `deferred/not_started -> stub -> complete -> verified` - Use `batch-update` with **at most 15 IDs** per call. - Never update IDs outside the current task group. - Never mark `verified` without corresponding build/test/stub-scan evidence. - If audit rejects status change, use `--override ""` only with explicit evidence. Templates: ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "" --set-status --db porting.db --execute dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "" --set-status --db porting.db --execute ``` ### Checkpoint Protocol Between Tasks (REQUIRED) At the end of each task before starting the next task: 1. Run Stub Detection Check. 2. Run Build Gate. 3. Run task-relevant Test Gate. 4. Run full unit suite: ```bash dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ ``` 5. Update status IDs for current task only (max 15 IDs per command). 6. Commit checkpoint changes. --- ## ANTI-STUB GUARDRAILS (NON-NEGOTIABLE) ### Forbidden Patterns (Features + Tests) Any of these in touched methods means the work is a stub and must not be promoted: - `throw new NotImplementedException()` - Empty mapped method bodies - Placeholder comments: `// TODO`, `// PLACEHOLDER`, `// later` - Fake-pass assertions: `Assert.True(true)`, `Assert.Pass()` - Tests that never call production code in `ZB.MOM.NatsNet.Server` - Constant-return placeholders for non-trivial logic (`return null;`, `return 0;`, `return false;`, `return string.Empty;`) without Go-equivalent behavior - Catch-all exception swallowing used to force pass behavior ### Hard Limits - Max feature IDs per group: `~20` - Max IDs per `feature/test batch-update`: `15` - One active feature loop at a time - No `verified` promotion unless build + targeted tests + stub scan are green - One checkpoint commit per task minimum - Feature `1519` must not be merged as partial/no-op behavior ### If You Get Stuck (MANDATORY) 1. Stop work on the blocked ID immediately. 2. Do **not** leave placeholder code or fake tests. 3. Mark the blocked item `deferred` with specific reason: ```bash dotnet run --project tools/NatsNet.PortTracker -- feature update --status deferred --override "blocked: " --db porting.db dotnet run --project tools/NatsNet.PortTracker -- test update --status deferred --override "blocked: " --db porting.db ``` 4. Move to the next unblocked ID in the same task. 5. Deferred-with-reason is correct behavior; stubs are not. --- ## Feature/Test Grouping (max ~20 per group) ### Group A (7 features): Batch lifecycle + store creation `1508,1509,1510,1511,1512,1513,1514` ### Group B (5 features): Staged/apply state + pre-proposal header checks `1515,1516,1517,1518,1519` ### Group C (3 tests): Raft-node behavioral tests mapped to batch 29 `2654,2674,2718` --- ### Task 1: Preflight and Batch Start **Files:** - Read: `docs/standards/dotnet-standards.md` - Read: `docs/plans/2026-02-27-batch-29-jetstream-batching-design.md` - Read: `golang/nats-server/server/jetstream_batching.go` - Read: `golang/nats-server/server/raft_test.go` (mapped lines) **Step 1: Dependency/readiness checks** Run: ```bash dotnet run --project tools/NatsNet.PortTracker -- batch show 27 --db porting.db dotnet run --project tools/NatsNet.PortTracker -- batch show 29 --db porting.db dotnet run --project tools/NatsNet.PortTracker -- batch ready --db porting.db ``` Expected: - Batch 29 is startable, dependency 27 satisfied. **Step 2: Start batch** Run: ```bash dotnet run --project tools/NatsNet.PortTracker -- batch start 29 --db porting.db ``` Expected: - Batch transitions to in-progress. **Step 3: Baseline build/test** Run: ```bash dotnet build dotnet/ dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ ``` Expected: - Known baseline captured before edits. **Step 4: Checkpoint protocol and commit** --- ### Task 2: Implement Group A Features (`1508-1514`) **Files:** - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamBatching.cs` - Optional modify if needed by compile/runtime wiring: - `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.cs` - `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamTypes.cs` - `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs` - Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamBatchingCoreTests.cs` **Step 1: Mark Group A as `stub` (single chunk, 7 IDs <= 15)** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "1508,1509,1510,1511,1512,1513,1514" --set-status stub --db porting.db --execute ``` **Step 2: Execute Per-Feature Verification Loop for each ID in Group A** Expected: - Lifecycle/store methods are behaviorally implemented and individually gated. **Step 3: Task-level gates + checkpoint protocol** Run: ```bash dotnet build dotnet/ dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStreamBatching" ``` **Step 4: Promote eligible Group A IDs to `complete` (blocked IDs stay `deferred`)** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "" --set-status complete --db porting.db --execute ``` **Step 5: After checkpoint evidence, promote eligible Group A IDs to `verified`** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "" --set-status verified --db porting.db --execute ``` --- ### Task 3: Implement Group B Features (`1515-1519`) **Files:** - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamBatching.cs` - Optional create/modify to isolate large method: - `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamBatching.HeaderChecks.cs` - Optional supporting updates if required by dependencies: - `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.cs` - `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamTypes.cs` - `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamErrors.cs` - Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamBatchingCoreTests.cs` **Step 1: Mark Group B as `stub` (single chunk, 5 IDs <= 15)** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "1515,1516,1517,1518,1519" --set-status stub --db porting.db --execute ``` **Step 2: Execute Per-Feature Verification Loop for each ID in Group B** Notes: - Treat `1519` as its own micro-loop: implement incrementally but only promote when full gate passes. - Validate error-path parity (duplicate msg ID, expected sequence checks, schedule/rollup validation, discard-new limits). **Step 3: Task-level gates + checkpoint protocol** Run: ```bash dotnet build dotnet/ dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStreamBatching" dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~RaftTypesTests" ``` **Step 4: Promote eligible Group B IDs to `complete` (blocked IDs stay `deferred`)** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "" --set-status complete --db porting.db --execute ``` **Step 5: After checkpoint evidence, promote eligible Group B IDs to `verified`** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "" --set-status verified --db porting.db --execute ``` --- ### Task 4: Implement Group C Tests (`2654,2674,2718`) **Files:** - Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/RaftNodeTests.cs` - Optional modify if helper setup reuse is needed: - `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/RaftTypesTests.cs` - Source references: - `golang/nats-server/server/raft_test.go` **Step 1: Mark tests as `stub`** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "2654,2674,2718" --set-status stub --db porting.db --execute ``` **Step 2: Execute Per-Test Verification Loop for each test ID** Expected: - Each mapped test method is real, discovered, and passing individually. **Step 3: Task-level gates + checkpoint protocol** Run: ```bash dotnet build dotnet/ dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~RaftNodeTests" ``` **Step 4: Promote eligible tests to `complete`** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "" --set-status complete --db porting.db --execute ``` **Step 5: After checkpoint evidence, promote eligible tests to `verified`** ```bash dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "" --set-status verified --db porting.db --execute ``` --- ### Task 5: Batch 29 Final Verification and Closeout **Files:** - Modify: `porting.db` - Generate: `reports/current.md` (via report script) **Step 1: Final mandatory gates** Run: ```bash dotnet build dotnet/ dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ dotnet run --project tools/NatsNet.PortTracker -- batch show 29 --db porting.db dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db ``` Expected: - All Batch 29 IDs are `verified` or `deferred` with explicit reasons. **Step 2: Complete batch** Run: ```bash dotnet run --project tools/NatsNet.PortTracker -- batch complete 29 --db porting.db ``` **Step 3: Generate report + commit** ```bash ./reports/generate-report.sh git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream \ porting.db reports/ git commit -m "feat(batch29): port jetstream batching and mapped raft tests" ```