Files
natsnet/docs/plans/2026-02-27-batch-36-stream-lifecycle-implementation-plan.md
Joseph Doherty f8dce79ac0 Add batch plans for batches 31-36 (rounds 16-18)
Generated design docs and implementation plans via Codex for:
- Batch 31: Raft Part 2
- Batch 32: JS Cluster Meta
- Batch 33: JS Cluster Streams
- Batch 34: JS Cluster Consumers
- Batch 35: JS Cluster Remaining
- Batch 36: Stream Lifecycle

All plans include mandatory verification protocol and anti-stub guardrails.
Updated batches.md with file paths and planned status.
2026-02-27 17:01:31 -05:00

16 KiB

Batch 36 Stream Lifecycle Implementation Plan

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

Goal: Port and verify Batch 36 (Stream Lifecycle) from server/stream.go so all 92 mapped features and 53 mapped tests are either genuinely implemented/verified or explicitly deferred with documented blockers.

Architecture: Implement in five bounded feature groups (20/20/20/20/12) aligned to NatsStream lifecycle domains (config/update, mirror, source, subscriptions) plus supporting Account, NatsServer, JsAccount, and stream type helpers. Execute four test waves with strict per-test evidence and anti-stub enforcement 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-36-stream-lifecycle-design.md


Batch 36 Scope

  • Batch ID: 36
  • Name: Stream Lifecycle
  • Dependencies: 8,11,12,13,14,15,28
  • Go source: golang/nats-server/server/stream.go
  • Features: 92 (3196-3293 mapped IDs)
  • 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/NatsStream.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Lifecycle.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Mirror.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Source.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Subscriptions.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/StoreTypes.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/StreamTypes.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamTypes.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JsAccount.StreamLifecycle.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/Accounts/Account.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/Accounts/Account.StreamLifecycle.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.StreamLifecycle.cs

Primary test files (expected):

  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsConsumerTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests2.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests1.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/StorageEngineTests.Impltests.cs
  • Create: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests1.Impltests.cs
  • Create: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests3.Impltests.cs

MANDATORY VERIFICATION PROTOCOL

NON-NEGOTIABLE: Every feature/test in Batch 36 must pass this loop. No shortcut status updates.

Dependency Preflight (before any status change)

$DOTNET run --project tools/NatsNet.PortTracker -- batch show 8 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 11 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 12 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 13 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 14 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 15 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 28 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 36 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- batch ready --db porting.db

Start only when ready:

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

Capture baseline:

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

Per-Feature Verification Loop (REQUIRED per feature ID)

  1. Inspect mapping and Go context:
$DOTNET run --project tools/NatsNet.PortTracker -- feature show <feature_id> --db porting.db
  1. Mark claim-in-progress:
$DOTNET run --project tools/NatsNet.PortTracker -- feature update <feature_id> --status stub --db porting.db
  1. Add/adjust focused test(s) for that feature behavior (red first when practical).
  2. Implement minimal real logic (no placeholder bodies).
  3. Run Stub Detection Check on touched files.
  4. Run Build Gate.
  5. Run targeted Test Gate for affected classes.
  6. If green, promote feature to complete (or verified only with checkpoint evidence).
  7. Record evidence before touching next feature.

Per-Test Verification Loop (REQUIRED per test ID)

  1. Inspect mapping and Go test location:
$DOTNET run --project tools/NatsNet.PortTracker -- test show <test_id> --db porting.db
  1. Mark claim-in-progress:
$DOTNET run --project tools/NatsNet.PortTracker -- test update <test_id> --status stub --db porting.db
  1. Port full Arrange/Act/Assert behavior against production code.
  2. Run the single test method:
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~<ClassName>.<MethodName>" --verbosity normal
  1. Confirm output shows Passed: 1, Failed: 0 (never Passed: 0).
  2. Run class-level filter for touched test class.
  3. Run Stub Detection Check + Build Gate.
  4. Promote test to complete (or verified only with checkpoint evidence).

Stub Detection Check (REQUIRED after every loop)

Run on changed C# files in source + tests:

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|ShouldContain\\(\"Should\"\\)|var goFile = \"server/|JetStreamVersioning\\.GetRequiredApiLevel\\(new Dictionary<string, string>\\)\\.ShouldBe\\(string\\.Empty\\)|=>\\s*default;|return\\s+default;|return\\s+null;\\s*$)"
fi

Any match in mapped Batch 36 methods/tests blocks promotion until resolved.

Build Gate (REQUIRED)

$DOTNET build dotnet/

Run:

  • after every feature loop
  • after every test loop
  • before any batch-update
  • at every task checkpoint

Test Gate (REQUIRED)

Minimum class/domain gates per touched area:

$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStreamEngineTests"
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStreamClusterTests"
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~NatsConsumerTests"
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~StorageEngineTests|FullyQualifiedName~JetStreamFileStoreTests|FullyQualifiedName~ConcurrencyTests1"

Checkpoint/full gate:

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

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

  • Never pass more than 15 IDs per feature batch-update or test batch-update call.
  • Never promote verified without loop evidence + checkpoint gate.
  • Never update IDs outside current task scope.
  • For blocked work, keep deferred with explicit reason.

Templates:

$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

Checkpoint Protocol Between Tasks (REQUIRED)

Before starting the next task:

  1. Run Stub Detection Check on current diff.
  2. Run Build Gate.
  3. Run class filters for all touched classes.
  4. Run full unit test gate.
  5. Promote only proven IDs in <=15 chunks.
  6. Commit checkpoint before the next task.

ANTI-STUB GUARDRAILS (NON-NEGOTIABLE)

Forbidden Patterns

These are forbidden in mapped Batch 36 features/tests:

  • throw new NotImplementedException()
  • Empty or no-op mapped method bodies
  • Placeholder comments (TODO, PLACEHOLDER, later)
  • Fake-pass assertions (Assert.True(true), Assert.Pass(), tautological string checks)
  • Template test bodies that only assert literals, including patterns such as:
    • var goFile = "server/..."
    • "<MethodName>".ShouldContain("Should")
    • JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty) as the core assertion
  • Constant-return shortcuts in mapped feature methods that ignore state/input (return default;, return null;, hardcoded primitives) unless directly required by Go behavior and covered by tests
  • Catch-and-ignore blocks used to force green tests

Hard Limits

  • Feature groups must stay at ~20 IDs max.
  • feature batch-update maximum IDs per call: 15.
  • test batch-update maximum IDs per call: 15.
  • One active feature loop at a time.
  • One active test loop at a time.
  • Mandatory checkpoint between every task.
  • No verified promotion without checkpoint evidence.

If You Get Stuck (REQUIRED)

  1. Stop on the current ID immediately.
  2. Do not add placeholder code or fake assertions.
  3. Mark blocked item deferred with explicit reason.
  4. Move to next unblocked ID.

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 a concrete blocker is correct. Stubbed progress is not.


Feature Groups (max ~20 each)

Group A (20): Stream creation, assignment, leadership primitives

IDs:
3196,3197,3198,3200,3201,3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3213,3214,3216,3217,3219

Group B (20): Limits, dedupe, advisories, config validation/update entry points

IDs:
3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3237,3238,3239,3240

Group C (20): Update internals, purge/delete, mirror processing/retry foundation

IDs:
3241,3242,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261

Group D (20): Source consumer setup, flow control, source header/sequence recovery

IDs:
3262,3263,3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281

Group E (12): Direct/mirror-direct subscriptions, internal subscribe/unsubscribe cleanup

IDs:
3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293

Test Waves

Wave T1 (15): file-store + cluster + consumer API basics

IDs:
548,849,869,902,951,953,955,990,1032,1034,1125,1227,1262,1315,1317

Wave T2 (12): stream create/update/publish baseline

IDs:
1468,1470,1471,1474,1475,1478,1480,1481,1482,1483,1504,1512

Wave T3 (12): limits, perf-sensitive behavior, republish cases

IDs:
1532,1544,1554,1555,1564,1565,1614,1623,1635,1636,1637,1638

Wave T4 (14): republish tail, direct get, versioning, concurrency/storage

IDs:
1639,1640,1644,1645,1646,1653,1656,1657,1669,1741,1743,2387,2402,2952


Task 1: Preflight and Baseline

Files:

  • Read: docs/plans/2026-02-27-batch-36-stream-lifecycle-design.md
  • Read: golang/nats-server/server/stream.go

Steps:

  1. Run dependency preflight commands.
  2. Start Batch 36 only if ready.
  3. Capture baseline build/test evidence.
  4. Do not promote any IDs before baseline evidence exists.

Task 2: Implement Feature Group A (20 IDs)

Files:

  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/StoreTypes.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/Accounts/Account.StreamLifecycle.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Lifecycle.cs

Steps:

  1. Move Group A IDs to stub using 15 + 5 update chunks.
  2. Execute Per-Feature Verification Loop per ID.
  3. Run mandatory gates after each ID.
  4. Promote proven IDs (complete/verified) in <=15 chunks.
  5. Run Checkpoint Protocol.

Task 3: Implement Feature Group B (20 IDs) + Test Wave T1 (15 IDs)

Files:

  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.StreamLifecycle.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JsAccount.StreamLifecycle.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Lifecycle.cs
  • Modify/Create: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests1.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests2.Impltests.cs
  • Modify/Create: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests3.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsConsumerTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.Impltests.cs

Steps:

  1. Implement Group B features with per-feature loop and gates.
  2. Port Wave T1 tests with per-test loop and gates.
  3. Apply status updates in max-15 chunks only.
  4. Run Checkpoint Protocol.

Task 4: Implement Feature Group C (20 IDs) + Test Wave T2 (12 IDs)

Files:

  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Lifecycle.cs
  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Mirror.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.Impltests.cs

Steps:

  1. Implement Group C feature IDs with per-feature loop.
  2. Port Wave T2 tests.
  3. Run stub/build/test gates and checkpoint.
  4. Promote only proven IDs in <=15 chunks.

Task 5: Implement Feature Group D (20 IDs) + Test Wave T3 (12 IDs)

Files:

  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Source.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/StreamTypes.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.Impltests.cs

Steps:

  1. Implement Group D features with per-feature loop.
  2. Port Wave T3 tests.
  3. Run mandatory gates and checkpoint.
  4. Promote only proven IDs in <=15 chunks.

Task 6: Implement Feature Group E (12 IDs) + Test Wave T4 (14 IDs)

Files:

  • Modify/Create: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Subscriptions.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/StorageEngineTests.Impltests.cs

Steps:

  1. Implement Group E feature IDs.
  2. Port Wave T4 tests.
  3. Run mandatory gates and checkpoint.
  4. Promote proven IDs in <=15 chunks.

Task 7: Batch 36 Final Closure

Files:

  • Modify: porting.db
  • Generate: reports/current.md (via report script)

Steps:

  1. Run final stub scan on all touched source/test files.
  2. Run full build and full unit suite.
  3. Validate batch state:
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 36 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- report summary --db porting.db
  1. Ensure every Batch 36 ID is complete/verified/n_a or deferred with explicit blocker notes.
  2. Generate report:
./reports/generate-report.sh

Execution note: Planning only. Do not execute this plan in this session.