Files
natsnet/docs/plans/2026-02-27-batch-39-consumer-dispatch-implementation-plan.md
Joseph Doherty 8a126c4932 Add batch plans for batches 37-41 (rounds 19-21)
Generated design docs and implementation plans via Codex for:
- Batch 37: Stream Messages
- Batch 38: Consumer Lifecycle
- Batch 39: Consumer Dispatch
- Batch 40: MQTT Server/JSA
- Batch 41: MQTT Client/IO

All plans include mandatory verification protocol and anti-stub guardrails.
Updated batches.md with file paths and planned status.
All 42 batches (0-41) now have design docs and implementation plans.
2026-02-27 17:27:51 -05:00

15 KiB

Batch 39 Consumer Dispatch Implementation Plan

For Codex: REQUIRED SUB-SKILL: Use executeplan to implement this plan task-by-task.

Goal: Port and verify Batch 39 (Consumer Dispatch) from server/consumer.go so all 93 mapped features and 53 mapped tests are either genuinely implemented/verified or explicitly deferred with concrete blocker reasons.

Architecture: Implement Batch 39 in five feature groups (18/18/19/19/19) with dispatch-focused NatsConsumer partial decomposition. After each feature group, execute mapped test waves and enforce strict evidence gates (stub scan, build gate, targeted tests, checkpoint) 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-39-consumer-dispatch-design.md


Batch 39 Scope

  • Batch ID: 39
  • Name: Consumer Dispatch
  • Dependency: 38
  • Go source: golang/nats-server/server/consumer.go
  • Features: 93
  • Tests: 53

If dotnet is not on PATH, use:

DOTNET=/usr/local/share/dotnet/dotnet

Primary production files (expected):

  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Waiting.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Pull.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Acks.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Delivery.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Redelivery.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.ReplyParsing.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Shutdown.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Consumers.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/StreamTypes.cs

Primary test files (expected):

  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/NatsConsumerTests.cs
  • Modify/Create: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/NatsConsumerDispatchTests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsConsumerTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests1.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JwtProcessorTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs
  • Create: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests1.Impltests.cs

MANDATORY VERIFICATION PROTOCOL

NON-NEGOTIABLE: Every Batch 39 feature and test must pass this protocol. No shortcuts.

1. Dependency Preflight and Baseline

Run before touching statuses:

$DOTNET run --project tools/NatsNet.PortTracker -- batch show 38 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 39 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- batch ready --db porting.db

Start Batch 39 only when ready:

$DOTNET run --project tools/NatsNet.PortTracker -- batch start 39 --db porting.db

Capture baseline:

$DOTNET build dotnet/
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/

2. What Counts as a Real Port

A feature is real only if all are true:

  1. Mapped method/type exists and contains behavioral logic (not placeholder control flow).
  2. Code path is exercised by at least one behavioral test.
  3. Stub scan, build gate, and targeted tests are green.
  4. Status promotion has traceable evidence.

A test is real only if all are true:

  1. Has Arrange/Act/Assert.
  2. Calls production code from ZB.MOM.NatsNet.Server.*.
  3. Uses meaningful Shouldly assertions on Act results/effects.
  4. Contains no stub/template patterns.

3. Per-Feature Verification Loop (REQUIRED per feature ID)

  1. Inspect mapped feature and Go source intent:
$DOTNET run --project tools/NatsNet.PortTracker -- feature show <feature_id> --db porting.db
  1. Claim the feature:
$DOTNET run --project tools/NatsNet.PortTracker -- feature update <feature_id> --status stub --db porting.db
  1. Add/adjust at least one behavioral test for the feature.
  2. Implement minimal correct logic.
  3. Run Stub Detection Check.
  4. Run Build Gate.
  5. Run relevant Test Gate filters.
  6. Promote proven feature to complete (or verified only after checkpoint evidence).

4. Per-Test Verification Loop (REQUIRED per test ID)

  1. Inspect mapped test and Go source:
$DOTNET run --project tools/NatsNet.PortTracker -- test show <test_id> --db porting.db
  1. Claim the test:
$DOTNET run --project tools/NatsNet.PortTracker -- test update <test_id> --status stub --db porting.db
  1. Port complete behavior.
  2. Run single test and verify discovery:
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~<ClassName>.<MethodName>" --verbosity normal
  1. Confirm Passed: 1, Failed: 0 (never Passed: 0).
  2. Run class-level filter.
  3. Run Stub Detection Check + Build Gate.
  4. Promote proven test to complete (or verified only after checkpoint evidence).

5. Stub Detection Check (REQUIRED after each feature/test loop)

changed_files=$(git diff --name-only -- dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests | rg "\\.cs$" || true)
if [ -n "$changed_files" ]; then
  echo "$changed_files" | xargs rg -n "(NotImplementedException|// TODO|// PLACEHOLDER|Assert\\.True\\(true\\)|Assert\\.Pass\\(\\)|var goFile = \"server/|\\.ShouldContain\\(\"Should\"\\)|GetRequiredApiLevel\\(new Dictionary<string, string>\\)\\.ShouldBe\\(string\\.Empty\\)|=>\\s*default;|return\\s+default;|return\\s+null;\\s*$|throw new Exception\\(\"TODO\"\\))"
fi

Any match blocks status promotion until fixed or explicitly deferred.

6. Build Gate (REQUIRED)

$DOTNET build dotnet/

Run after every feature loop, every test loop, before any batch-update, and at each task checkpoint.

7. Test Gate (REQUIRED)

Run the smallest relevant set after each change; run all of the following at checkpoints:

$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStream.NatsConsumerTests|FullyQualifiedName~JetStream.NatsConsumerDispatchTests"
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ImplBacklog.NatsConsumerTests|FullyQualifiedName~ImplBacklog.JetStreamEngineTests"
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ImplBacklog.JetStreamClusterTests1|FullyQualifiedName~ImplBacklog.ConcurrencyTests1|FullyQualifiedName~ImplBacklog.JwtProcessorTests|FullyQualifiedName~ImplBacklog.RouteHandlerTests"

Checkpoint/full gate:

$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/

8. Status Update Protocol (HARD LIMIT: 15 IDs per batch-update)

  • Never send more than 15 IDs per feature batch-update or test batch-update call.
  • Never mark verified without checkpoint evidence.
  • Never update IDs outside the active task scope.
  • Keep blocked items deferred with specific reason text.

Use:

$DOTNET run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "<max 15 ids>" --set-status <stub|complete|verified> --db porting.db --execute

$DOTNET run --project tools/NatsNet.PortTracker -- \
  test batch-update --ids "<max 15 ids>" --set-status <stub|complete|verified> --db porting.db --execute

9. Checkpoint Protocol Between Tasks (REQUIRED)

Before moving to the next task:

  1. Run Stub Detection Check.
  2. Run Build Gate.
  3. Run Test Gate (targeted filters + full unit test suite).
  4. Apply status updates in max-15-ID chunks only.
  5. Commit the task checkpoint before continuing.

ANTI-STUB GUARDRAILS (NON-NEGOTIABLE)

Forbidden Patterns

The following are forbidden in Batch 39 feature/test work:

  • throw new NotImplementedException()
  • Empty mapped method bodies / no-op ports
  • TODO / PLACEHOLDER comments as unresolved implementation markers
  • Assert.True(true) / Assert.Pass()
  • Template assertions disconnected from behavior:
    • var goFile = "server/..."
    • "<name>".ShouldContain("Should")
    • GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty) as primary assertion
  • Placeholder return shortcuts in mapped code:
    • => default;
    • return default;
    • return null;
  • Catch-and-ignore blocks used only to force green tests

Hard Limits

  • Max feature group size: ~20.
  • Max IDs per feature batch-update: 15.
  • Max IDs per test batch-update: 15.
  • One active feature loop at a time.
  • One active test loop at a time.
  • Mandatory checkpoint between tasks.
  • No verified promotion without checkpoint evidence.

If You Get Stuck (REQUIRED)

  1. Stop on the current feature/test immediately.
  2. Do not stub or fake-pass.
  3. Mark item deferred with a specific blocker reason.
  4. Continue with the next unblocked item.

Feature deferral:

$DOTNET run --project tools/NatsNet.PortTracker -- \
  feature update <feature_id> --status deferred --override "blocked: <specific reason>" --db porting.db

Test deferral:

$DOTNET run --project tools/NatsNet.PortTracker -- \
  test update <test_id> --status deferred --override "blocked: <specific reason>" --db porting.db

deferred with concrete reason is the correct fallback; stubs are not.


Feature Groups (max ~20 each)

Group A (18): waiting queue and pull ingress

IDs:
696,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715

Group B (18): dispatch core, ack floor, inbound loops

IDs:
716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733

Group C (19): delivery, flow-control, redelivery basics

IDs:
734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752

Group D (19): reply parsing, seq selection, identity helpers

IDs:
753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,772

Group E (19): purge/stop/no-interest/monitor signaling

IDs:
774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792

Test Waves

Wave T1 (14): NatsConsumerTests

IDs:
1230,1232,1251,1261,1265,1267,1273,1277,1283,1284,1285,1286,1339,1370

Wave T2 (17): JetStreamEngineTests (pull/ack-first half)

IDs:
1469,1484,1485,1486,1487,1488,1489,1490,1492,1493,1495,1496,1498,1499,1500,1501,1502

Wave T3 (17): JetStreamEngineTests (pending/purge-second half)

IDs:
1508,1514,1515,1516,1517,1518,1519,1520,1521,1522,1526,1530,1531,1545,1547,1567,1665

Wave T4 (5): cross-suite integration/backlog edges

IDs:
814,1840,2389,2407,2858


Task 1: Preflight and Baseline

Files:

  • Read: docs/plans/2026-02-27-batch-39-consumer-dispatch-design.md
  • Read: golang/nats-server/server/consumer.go

Steps:

  1. Run dependency preflight and confirm Batch 39 readiness.
  2. Start Batch 39.
  3. Capture baseline build + full unit test results.
  4. Record baseline pass/fail/skip counts.

Task 2: Implement Feature Group A + Test Wave T1

Files:

  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Waiting.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Pull.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/StreamTypes.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/NatsConsumerTests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsConsumerTests.Impltests.cs

Steps:

  1. Process each feature ID in Group A through the per-feature loop.
  2. Port all tests in Wave T1 with per-test loop.
  3. Run checkpoint protocol.
  4. Update Group A/T1 statuses in max-15-ID chunks.
  5. Commit.

Task 3: Implement Feature Group B

Files:

  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Pull.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Acks.cs
  • Modify/Create: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/NatsConsumerDispatchTests.cs

Steps:

  1. Process Group B feature IDs through per-feature loop.
  2. Add deterministic unit tests for dispatch loop and ack-floor transitions.
  3. Run checkpoint protocol.
  4. Update Group B feature statuses in max-15-ID chunks.
  5. Commit.

Task 4: Implement Feature Group C + Test Wave T2

Files:

  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Delivery.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Redelivery.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.Impltests.cs

Steps:

  1. Process Group C feature IDs through per-feature loop.
  2. Port Wave T2 tests through per-test loop.
  3. Run checkpoint protocol.
  4. Update Group C/T2 statuses in max-15-ID chunks.
  5. Commit.

Task 5: Implement Feature Group D + Test Wave T3

Files:

  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.ReplyParsing.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Consumers.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.Impltests.cs

Steps:

  1. Process Group D feature IDs through per-feature loop.
  2. Port Wave T3 tests through per-test loop.
  3. Run checkpoint protocol.
  4. Update Group D/T3 statuses in max-15-ID chunks.
  5. Commit.

Task 6: Implement Feature Group E + Test Wave T4

Files:

  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Shutdown.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.cs
  • Modify/Create: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests1.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests1.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JwtProcessorTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs

Steps:

  1. Process Group E feature IDs through per-feature loop.
  2. Port Wave T4 tests through per-test loop.
  3. Run checkpoint protocol.
  4. Update Group E/T4 statuses in max-15-ID chunks.
  5. Commit.

Task 7: Final Batch 39 Verification and Closure

Files:

  • Modify: porting.db
  • Generate: reports/current.md

Steps:

  1. Run full stub scan over changed source + test files.
  2. Run full build gate.
  3. Run full unit test suite; require Failed: 0.
  4. Run:
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 39 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- report summary --db porting.db
  1. If all IDs are complete/verified/deferred-with-reason, execute batch completion:
$DOTNET run --project tools/NatsNet.PortTracker -- batch complete 39 --db porting.db
  1. Generate updated report and commit:
./reports/generate-report.sh
git add dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests porting.db reports/
git commit -m "feat(batch39): implement consumer dispatch features and tests"