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

482 lines
18 KiB
Markdown

# 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:
```bash
/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:
```bash
/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:
```bash
# 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:
```bash
/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:
```bash
/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:
```bash
/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:
```bash
/usr/local/share/dotnet/dotnet build dotnet/
```
2. Full unit suite:
```bash
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal
```
3. Commit checkpoint:
```bash
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:
```bash
/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**
```bash
/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**
```bash
/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**
```bash
/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**
```bash
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**
```bash
/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**
```bash
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**
```bash
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**
```bash
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**
```bash
/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)**
```bash
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**
```bash
/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**
```bash
/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**
```bash
./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"
```