# 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:

```bash
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)

```bash
$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:

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

Capture baseline:

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

### Per-Test Verification Loop (REQUIRED per test ID)

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

```bash
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)

```bash
$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:

```bash
$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:

```bash
$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:

```bash
$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:

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

Test deferral:

```bash
$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:
```bash
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 36 --db porting.db
$DOTNET run --project tools/NatsNet.PortTracker -- report summary --db porting.db
```
4. Ensure every Batch 36 ID is `complete/verified/n_a` or `deferred` with explicit blocker notes.
5. Generate report:
```bash
./reports/generate-report.sh
```

---

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