Files
natsnet/docs/plans/2026-02-27-batch-14-filestore-write-lifecycle-plan.md
Joseph Doherty dc3e162608 Add batch plans for batches 13-15, 18-22 (rounds 8-11)
Generated design docs and implementation plans via Codex for:
- Batch 13: FileStore Read/Query
- Batch 14: FileStore Write/Lifecycle
- Batch 15: MsgBlock + ConsumerFileStore
- Batch 18: Server Core
- Batch 19: Accounts Core
- Batch 20: Accounts Resolvers
- Batch 21: Events + MsgTrace
- Batch 22: Monitoring

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

18 KiB

Batch 14 FileStore Write/Lifecycle Implementation Plan

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

Goal: Implement and verify all Batch 14 FileStore write/lifecycle features and mapped tests from server/filestore.go with non-stub behavior and evidence-backed status transitions.

Architecture: Execute Batch 14 in four vertical feature groups (18 + 18 + 20 + 20) aligned to filestore.go locality and lifecycle boundaries. After each feature group, run strict stub/build/test gates, then port and verify the dependency-resolved test wave before any verified status changes. Keep implementation centered in JetStream/FileStore.cs, with targeted support updates in MessageBlock.cs and FileStoreTypes.cs only when required by Go parity.

Tech Stack: .NET 10, C# latest, xUnit 3, Shouldly, NSubstitute, PortTracker CLI, SQLite (porting.db)


I'm using writeplan to create the implementation plan.

Design doc: docs/plans/2026-02-27-batch-14-filestore-write-lifecycle-design.md

Batch Inputs

  • Batch: 14 (FileStore Write/Lifecycle)
  • Depends on: Batch 13
  • Features: 76
  • Tests: 64
  • Go source: golang/nats-server/server/filestore.go

Feature groups (max ~20 each):

  • Group 1 (18): 1020,1024,1027,1028,1029,1036,1037,1038,1039,1040,1041,1042,1045,1046,1047,1048,1054,1066
  • Group 2 (18): 1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1099,1100,1101,1102,1108,1109,1110,1111
  • Group 3 (20): 1131,1132,1133,1139,1140,1147,1148,1160,1161,1162,1168,1169,1171,1172,1178,1179,1180,1181,1182,1183
  • Group 4 (20): 1184,1189,1193,1195,1197,1198,1199,1201,1202,1203,1204,1205,1207,1208,1210,1211,1212,1214,1215,1260

Test waves (dependency-resolved):

  • Wave 1 (8): 549,551,561,572,586,587,1219,2441
  • Wave 2 (6): 354,365,372,435,593,2476
  • Wave 3 (27): 363,378,418,437,438,442,452,455,457,461,462,464,470,475,476,485,490,491,492,494,495,496,498,501,503,523,2480
  • Wave 4 (23): 384,412,413,477,483,518,519,530,531,566,567,588,589,590,594,1899,1900,1901,1984,2001,2431,2494,2854

Primary test files:

  • dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.Impltests.cs
  • dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests1.Impltests.cs
  • dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests2.Impltests.cs
  • dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/LeafNodeHandlerTests.Impltests.cs
  • dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs
  • Create if missing:
    • dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/LeafNodeProxyTests.Impltests.cs
    • dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterLongTests.Impltests.cs

MANDATORY VERIFICATION PROTOCOL

NON-NEGOTIABLE: Every feature/test task and every status update must pass this protocol.

Per-Feature Verification Loop (REQUIRED for every feature ID)

For each active feature ID:

  1. Read feature mapping and Go intent:
    /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- feature show <FEATURE_ID> --db porting.db
    
  2. Read exact Go method body and nearby helpers in golang/nats-server/server/filestore.go.
  3. Write minimal real C# behavior in FileStore/MessageBlock/FileStoreTypes.
  4. Build immediately:
    /usr/local/share/dotnet/dotnet build dotnet/
    
  5. Run targeted related tests for that behavior (single method or tight class filter).
  6. Only then add the feature ID to status-update candidates.

Stub Detection Check (REQUIRED after each feature group and test wave)

Any match below is a blocker:

# Production stubs/placeholders
rg -n "NotImplementedException|TODO|PLACEHOLDER|throw new NotSupportedException" \
  dotnet/src/ZB.MOM.NatsNet.Server/JetStream -g '*.cs'

# Empty production bodies on FileStore surface
rg -n "^\s*(public|private|internal|protected).*(\)\s*\{\s*\}|=>\s*default;|=>\s*null;)" \
  dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/JetStream/MessageBlock.cs

# Test placeholders and always-pass patterns
rg -n "NotImplementedException|Assert\.True\(true\)|Assert\.Pass|// TODO|// PLACEHOLDER|ShouldBe\(true\);" \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/*.cs

# Existing placeholder-template smell (must be removed from ported tests)
rg -n "goFile\.ShouldStartWith\(\"server/\"\)|ServerConstants\.DefaultPort\.ShouldBe\(4222\)" \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/*.cs

Build Gate (REQUIRED after each feature group)

Before any status update for that group:

/usr/local/share/dotnet/dotnet build dotnet/

Build must pass with zero errors.

Test Gate (REQUIRED before marking features verified)

All related tests for the active scope must pass before any feature in that scope can be marked verified.

Minimum gate commands:

/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.ImplBacklog.JetStreamFileStoreTests" \
  --verbosity normal

/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.ImplBacklog.ConcurrencyTests1|FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.ImplBacklog.ConcurrencyTests2|FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.ImplBacklog.LeafNodeHandlerTests|FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.ImplBacklog.LeafNodeProxyTests|FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.ImplBacklog.RouteHandlerTests|FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.ImplBacklog.JetStreamClusterLongTests" \
  --verbosity normal

Status Update Protocol (REQUIRED)

  • Max 15 IDs per feature batch-update or test batch-update command.
  • Required progression:
    • Features: deferred -> stub -> complete -> verified
    • Tests: deferred -> stub -> verified (or stay deferred with reason)
  • Evidence is mandatory before each update:
    • Go method reviewed
    • build passed
    • related tests passed
    • stub scan clean
  • Keep evidence logs under /tmp/batch14-evidence/.

Example update command:

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "1020,1024,1027" --set-status complete --db porting.db --execute

Checkpoint Protocol Between Tasks (REQUIRED)

Between each feature/test group transition:

  1. Full build:
    /usr/local/share/dotnet/dotnet build dotnet/
    
  2. Full unit suite:
    /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal
    
  3. Commit checkpoint:
    git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream \
      dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog \
      porting.db
    git commit -m "feat(batch14): complete group <N> filestore write lifecycle"
    

ANTI-STUB GUARDRAILS

Forbidden Patterns

Do not introduce or keep any of these in Batch 14 feature/test scope:

  • throw new NotImplementedException(...)
  • Empty mapped method bodies ({ }) in FileStore.cs/MessageBlock.cs
  • TODO/PLACEHOLDER markers in implemented methods/tests
  • Always-pass tests (Assert.True(true), Assert.Pass, trivial constants-only assertions)
  • Placeholder-template tests that only validate static constants or method names
  • Tests with no production behavior act step against FileStore APIs

Hard Limits

  • Max ~20 features per implementation group (fixed at 18/18/20/20)
  • Max 15 IDs per status update command
  • Max one feature group per status-update cycle
  • Zero stub-scan hits before complete or verified
  • No verified transition without Build Gate + Test Gate evidence

If You Get Stuck (MANDATORY)

  1. Do not write stubs, no-ops, or fake pass tests.
  2. Mark only blocked IDs as deferred with concrete reason.
  3. Continue with unblocked IDs in the same group.
  4. Record blocker evidence and use override reason text.

Example:

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature update <ID> --status deferred --db porting.db \
  --override "blocked: requires <specific infra/dependency> for non-stub implementation"

Use same pattern for tests.


Task 1: Batch Start, Baseline, and Staging

Files:

  • Modify: porting.db
  • Create: /tmp/batch14-evidence/

Step 1: Confirm batch state

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 14 --db porting.db
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch list --db porting.db
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db

Expected: Batch 14 pending with dependency on 13.

Step 2: Start batch

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch start 14 --db porting.db

Step 3: Stage Group 1 IDs to stub

Run chunked updates (<=15 IDs each) for Group 1 features and Wave 1 tests.

Step 4: Baseline build/test

/usr/local/share/dotnet/dotnet build dotnet/
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal

Step 5: Commit baseline checkpoint

git add porting.db docs/plans/2026-02-27-batch-14-filestore-write-lifecycle-design.md docs/plans/2026-02-27-batch-14-filestore-write-lifecycle-plan.md
git commit -m "plan(batch14): establish filestore write lifecycle execution baseline"

Task 2: Implement Group 1 Features (18 IDs)

Files:

  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/MessageBlock.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStoreTypes.cs

Step 1: Port write-path foundations

Feature IDs: 1020,1024,1027,1028,1029

Step 2: Port sequence and limit/removal paths

Feature IDs: 1036,1037,1038,1039,1040,1041,1042,1045,1046,1047,1048,1054,1066

Step 3: Apply mandatory verification protocol

Run per-feature loop, stub scans, and build gate for all 18 IDs.

Step 4: Update Group 1 feature status

  • Move to complete in chunks <=15.
  • Move to verified only after Wave 1 test gate passes.

Task 3: Port and Verify Wave 1 Tests (8 IDs)

Files:

  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests1.Impltests.cs
  • Create: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterLongTests.Impltests.cs

Wave 1 IDs: 549,551,561,572,586,587,1219,2441

Step 1: Read Go tests via test show <ID> and implement real behavior tests

Step 2: Run each test method individually, verify discovery and pass

/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~<TestMethodName>" --verbosity normal

Step 3: Run class-level test gates for modified classes

Step 4: Run stub scans and build gate

Step 5: Update Wave 1 test statuses to verified (<=15 IDs per command)

Task 4: Group 1 Checkpoint

Files:

  • Modify: porting.db

Step 1: Run checkpoint protocol

Step 2: Commit Group 1 checkpoint

git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog porting.db
git commit -m "feat(batch14): complete group1 write path and wave1 tests"

Task 5: Implement Group 2 Features (18 IDs)

Files:

  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/MessageBlock.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStoreTypes.cs

Feature IDs: 1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1099,1100,1101,1102,1108,1109,1110,1111

Step 1: Port age-check, scheduling, and check/flush loops

Step 2: Port message record/tombstone and block sync/select helpers

Step 3: Apply mandatory verification protocol

Step 4: Update Group 2 feature statuses (chunked <=15)

Task 6: Port and Verify Wave 2 Tests (6 IDs)

Files:

  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests2.Impltests.cs

Wave 2 IDs: 354,365,372,435,593,2476

Step 1: Implement tests from Go source intent

Step 2: Execute per-test loop + class-level gate

Step 3: Run stub scans/build gate and verify no placeholder-template remnants

Step 4: Mark Wave 2 tests verified (<=15 IDs per call)

Task 7: Group 2 Checkpoint

Files:

  • Modify: porting.db

Step 1: Run checkpoint protocol

Step 2: Commit Group 2 checkpoint

git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog porting.db
git commit -m "feat(batch14): complete group2 lifecycle checks and wave2 tests"

Task 8: Implement Group 3 Features (20 IDs)

Files:

  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/MessageBlock.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStoreTypes.cs

Feature IDs: 1131,1132,1133,1139,1140,1147,1148,1160,1161,1162,1168,1169,1171,1172,1178,1179,1180,1181,1182,1183

Step 1: Port seq/message/load helpers and cache/state accessors

Step 2: Port purge/compact/reset and block list management methods

Step 3: Apply mandatory verification protocol

Step 4: Update Group 3 feature statuses (<=15 IDs per command)

Task 9: Port and Verify Wave 3 Tests (27 IDs)

Files:

  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests2.Impltests.cs

Wave 3 IDs: 363,378,418,437,438,442,452,455,457,461,462,464,470,475,476,485,490,491,492,494,495,496,498,501,503,523,2480

Step 1: Implement tests in sub-batches of 10-12 methods

Step 2: For each sub-batch, run per-test loop and class gate

Step 3: Run mandatory stub/build/test gates

Step 4: Mark Wave 3 tests verified in max-15 ID chunks

Task 10: Group 3 Checkpoint

Files:

  • Modify: porting.db

Step 1: Run checkpoint protocol

Step 2: Commit Group 3 checkpoint

git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog porting.db
git commit -m "feat(batch14): complete group3 purge compact state and wave3 tests"

Task 11: Implement Group 4 Features (20 IDs)

Files:

  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/MessageBlock.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStoreTypes.cs

Feature IDs: 1184,1189,1193,1195,1197,1198,1199,1201,1202,1203,1204,1205,1207,1208,1210,1211,1212,1214,1215,1260

Step 1: Port purge-block/global subject info and stream-state write loops

Step 2: Port stop/snapshot/read-lock-all/delete-map/delete-blocks/write-file-with-optional-sync lifecycle methods

Step 3: Apply mandatory verification protocol

Step 4: Update Group 4 feature statuses (<=15 IDs per command)

Task 12: Port and Verify Wave 4 Tests (23 IDs)

Files:

  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/LeafNodeHandlerTests.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests1.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests2.Impltests.cs
  • Modify: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs
  • Create: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/LeafNodeProxyTests.Impltests.cs

Wave 4 IDs: 384,412,413,477,483,518,519,530,531,566,567,588,589,590,594,1899,1900,1901,1984,2001,2431,2494,2854

Step 1: Implement file-store lifecycle tests in JetStreamFileStoreTests.Impltests.cs

Step 2: Implement cross-module backlog tests (leaf/proxy/route/concurrency) only with real behavior assertions

Step 3: If any test requires unavailable infra, mark that test deferred with explicit reason (no stubs)

Step 4: Run per-test loop, class gates, stub scans, and build gate

Step 5: Mark verified/deferred statuses in <=15 ID chunks with evidence

Task 13: Final Verification, Audit, and Batch Closure

Files:

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

Step 1: Full regression gates

/usr/local/share/dotnet/dotnet build dotnet/
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal

Step 2: Global stub audit (features + tests)

rg -n "NotImplementedException|TODO|PLACEHOLDER|Assert\.True\(true\)|Assert\.Pass|goFile\.ShouldStartWith\(\"server/\"\)" \
  dotnet/src/ZB.MOM.NatsNet.Server/JetStream \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog

Step 3: Run PortTracker audits

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- audit --type features --db porting.db
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- audit --type tests --db porting.db

Step 4: Verify batch visibility and complete

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 14 --db porting.db
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch complete 14 --db porting.db
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db

Step 5: Generate report and final commit

./reports/generate-report.sh
git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog porting.db reports/
git commit -m "feat(batch14): complete filestore write lifecycle features and tests"