# Batch 5 (JetStream Errors) Implementation Plan

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

**Goal:** Implement and verify Batch 5 JetStream error helper parity (`206` features) and resolve the `11` mapped tests with evidence-backed status updates.

**Architecture:** Keep canonical `JsApiError` constants in hand-authored code, add missing helper parity (`ParseOpts`, `ToReplacerArgs`), and generate constructor surface for all missing `NewJS*Error` methods in grouped increments (<=20 features). Use strict verification gates after each group: stub scan, build, focused tests, and status updates in <=15-ID chunks with captured evidence.

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

**Design doc:** `docs/plans/2026-02-27-batch-5-jetstream-errors-design.md`

---

## Batch 5 Working Set

Batch facts:

- Batch ID: `5`
- Features: `206` (all currently `deferred`)
- Tests: `11` (all currently `deferred`)
- Dependencies: none
- Go sources: `server/jetstream_errors.go`, `server/jetstream_errors_generated.go`

Feature groups (<=20 features each):

- **Group 01 (20):** `1751,1752,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772`
- **Group 02 (20):** `1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792`
- **Group 03 (20):** `1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812`
- **Group 04 (20):** `1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832`
- **Group 05 (20):** `1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852`
- **Group 06 (20):** `1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872`
- **Group 07 (20):** `1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892`
- **Group 08 (20):** `1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912`
- **Group 09 (20):** `1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932`
- **Group 10 (20):** `1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952`
- **Group 11 (6):** `1953,1954,1955,1956,1957,1958`

Mapped tests in this batch:

- `742`, `1304`, `1476`, `1606`, `1694`, `1696`, `1708`, `1757`, `1767`, `1777`, `2272`

Batch-5-linked features referenced by those tests:

- `1765`, `1806`, `1821`, `1876`, `1883`, `1903`, `1916`, `1930`, `1938`, `1953`

---

## MANDATORY VERIFICATION PROTOCOL

> **NON-NEGOTIABLE:** this protocol applies to every feature group and every test task.

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

1. Read the mapped Go source (`feature show <id>` + source file/line).
2. Implement or update mapped C# method in the mapped class.
3. Run focused constructor/helper tests for that feature group.
4. Run build gate.
5. Run related test gate.
6. Only then add the feature ID to `complete`/`verified` candidate lists.

Focused run pattern:

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~JetStreamErrorsGeneratedConstructorsTests.ConstructorSurface_Group<NN>" \
  --verbosity normal
```

### Stub Detection Check (REQUIRED after every feature group and test class)

Run on touched files only:

```bash
rg -n "NotImplementedException|throw new NotSupportedException\(|TODO|PLACEHOLDER" \
  dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamErrors*.cs \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/*.cs \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server/*.cs

rg -n "Assert\.True\(true\)|Assert\.Pass\(|\.ShouldBe\(true\);$|^\s*\{\s*\}$" \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/*.cs \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server/*.cs
```

Any hit in edited code blocks status promotion until resolved or explicitly deferred.

### Build Gate (REQUIRED after each feature group)

```bash
dotnet build dotnet/
```

Required: zero errors.

### Test Gate (REQUIRED before marking any feature `verified`)

Run all related classes and require `Failed: 0`:

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~JetStreamErrorsTests|FullyQualifiedName~JetStreamErrorsGeneratedConstructorsTests" \
  --verbosity normal
```

For the 10 features linked to tracked tests (`1765,1806,1821,1876,1883,1903,1916,1930,1938,1953`), related mapped test IDs must also pass before those features can move to `verified`. If those tests are infra-blocked, keep those features at `complete` and document blocker.

### Status Update Protocol (REQUIRED)

- Maximum `15` IDs per `feature batch-update` or `test batch-update` command.
- Evidence is required for every status update chunk:
  - focused test pass output
  - build gate output
  - related test gate output
  - stub scan output
- State progression:
  - Features: `deferred -> stub -> complete -> verified`
  - Tests: `deferred -> stub -> verified` (or stay `deferred` with explicit reason)

Command templates:

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "<max15ids>" --set-status stub --db porting.db --execute

dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "<max15ids>" --set-status complete --db porting.db --execute

dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "<max15ids>" --set-status verified --db porting.db --execute

dotnet run --project tools/NatsNet.PortTracker -- \
  test batch-update --ids "<max15ids>" --set-status verified --db porting.db --execute
```

If audit disagrees, use explicit reason:

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature update <id> --status verified --db porting.db \
  --override "manual verification evidence: <short reason>"
```

### Checkpoint Protocol Between Tasks (REQUIRED)

After each feature group task and each test-class task:

1. Full build:

```bash
dotnet build dotnet/
```

2. Full unit tests:

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal
```

3. Full integration tests:

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.IntegrationTests/ --verbosity normal
```

4. Commit the task slice before moving on.

---

## ANTI-STUB GUARDRAILS (NON-NEGOTIABLE)

### Forbidden Patterns

Production code forbidden:

- `throw new NotImplementedException()`
- `return default;` / `return null;` placeholders not present in Go logic
- Empty public method bodies used as placeholders
- `TODO`, `PLACEHOLDER`, or equivalent unresolved markers

Test code forbidden (for tests marked `verified`):

- `Assert.True(true)`
- `Assert.Pass()`
- String/self-assertions unrelated to behavior
- Empty method body without `[Fact(Skip = ...)]`
- Any test that does not exercise production code path

### Hard Limits

- Max `20` features per task group.
- Max `15` IDs per status update command.
- Max `1` feature group promoted per verification cycle.
- No feature gets `verified` without passing test gate evidence.
- No test gets `verified` if skipped.

### If You Get Stuck (Explicit Protocol)

Do not stub. Do not fake-pass tests.

1. Keep item `deferred`.
2. Add concrete blocker reason (server runtime, cluster harness, missing infra dependency, etc.).
3. Capture evidence command output proving blocker.
4. Continue with next unblocked item.

Commands:

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

dotnet run --project tools/NatsNet.PortTracker -- \
  test update <id> --status deferred --db porting.db \
  --override "blocked: <specific reason>"
```

---

### Task 1: Build Constructor/Test Harness Foundation (Group 01 baseline)

**Files:**

- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamErrors.cs`
- Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamErrors.GeneratedConstructors.cs`
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamErrorsTests.cs`
- Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamErrorsGeneratedConstructorsTests.cs`
- Create: `tools/generate-jetstream-errors.sh` (or equivalent deterministic generator script)
- Modify: `porting.db`

**Step 1: Mark Group 01 as `stub` (<=15 IDs per command)**

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "1751,1752,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767" \
  --set-status stub --db porting.db --execute

dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "1768,1769,1770,1771,1772" \
  --set-status stub --db porting.db --execute
```

**Step 2: Write failing tests for Group 01 constructor surface + helper parity**

- Add failing coverage for:
  - `Unless`/`ParseOpts` override behavior
  - `ToReplacerArgs` parity conversions (`string`, `Exception`, generic object)
  - Group 01 constructor method existence and output parity

**Step 3: Run focused tests to confirm FAIL**

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~JetStreamErrorsGeneratedConstructorsTests.ConstructorSurface_Group01" --verbosity normal
```

**Step 4: Implement Group 01 methods + helper parity**

- Implement mapped helper methods (`ParseOpts`, `ToReplacerArgs`) and Group 01 constructors.

**Step 5: Re-run focused tests and confirm PASS**

**Step 6: Run stub scan + build gate + test gate**

Use protocol commands above.

**Step 7: Promote Group 01 statuses to `complete` then `verified`**

Use the same two ID chunks as Step 1, first `complete`, then `verified`.

**Step 8: Checkpoint + commit**

```bash
git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamErrors.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamErrors.GeneratedConstructors.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamErrorsTests.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamErrorsGeneratedConstructorsTests.cs \
        tools/generate-jetstream-errors.sh porting.db

git commit -m "feat(batch5): implement jetstream error helpers and group01 constructors"
```

---

### Task 2: Implement Feature Group 02 (20 features)

**IDs:** `1773-1792`

**Files:**

- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamErrors.GeneratedConstructors.cs`
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamErrorsGeneratedConstructorsTests.cs`
- Modify: `porting.db`

**Execution Steps (repeat pattern for this and all later feature groups):**

1. Set `stub` in <=15 chunks:
   - `1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787`
   - `1788,1789,1790,1791,1792`
2. Add/enable failing Group 02 tests.
3. Run Group 02 focused tests and confirm fail.
4. Implement constructors for Group 02.
5. Run Group 02 focused tests and confirm pass.
6. Run stub scan + build gate + test gate.
7. Set `complete` in same 2 chunks.
8. Set `verified` in same 2 chunks.
9. Run checkpoint protocol and commit.

---

### Task 3: Implement Feature Group 03 (20 features)

**IDs:** `1793-1812`

**Status chunks:**

- Chunk A: `1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807`
- Chunk B: `1808,1809,1810,1811,1812`

Follow Task 2 steps verbatim (stub -> failing tests -> implementation -> pass -> gates -> complete -> verified -> checkpoint commit).

---

### Task 4: Implement Feature Group 04 (20 features)

**IDs:** `1813-1832`

**Status chunks:**

- Chunk A: `1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827`
- Chunk B: `1828,1829,1830,1831,1832`

Follow Task 2 steps verbatim.

---

### Task 5: Implement Feature Group 05 (20 features)

**IDs:** `1833-1852`

**Status chunks:**

- Chunk A: `1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847`
- Chunk B: `1848,1849,1850,1851,1852`

Follow Task 2 steps verbatim.

---

### Task 6: Implement Feature Group 06 (20 features)

**IDs:** `1853-1872`

**Status chunks:**

- Chunk A: `1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867`
- Chunk B: `1868,1869,1870,1871,1872`

Follow Task 2 steps verbatim.

---

### Task 7: Implement Feature Group 07 (20 features)

**IDs:** `1873-1892`

**Status chunks:**

- Chunk A: `1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887`
- Chunk B: `1888,1889,1890,1891,1892`

Follow Task 2 steps verbatim.

---

### Task 8: Implement Feature Group 08 (20 features)

**IDs:** `1893-1912`

**Status chunks:**

- Chunk A: `1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907`
- Chunk B: `1908,1909,1910,1911,1912`

Follow Task 2 steps verbatim.

---

### Task 9: Implement Feature Group 09 (20 features)

**IDs:** `1913-1932`

**Status chunks:**

- Chunk A: `1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927`
- Chunk B: `1928,1929,1930,1931,1932`

Follow Task 2 steps verbatim.

---

### Task 10: Implement Feature Group 10 (20 features)

**IDs:** `1933-1952`

**Status chunks:**

- Chunk A: `1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947`
- Chunk B: `1948,1949,1950,1951,1952`

Follow Task 2 steps verbatim.

---

### Task 11: Implement Feature Group 11 (6 features)

**IDs:** `1953,1954,1955,1956,1957,1958`

**Steps:**

1. Set all 6 to `stub` in one command.
2. Add/enable failing Group 11 tests.
3. Run focused Group 11 tests and confirm fail.
4. Implement constructors for Group 11.
5. Re-run focused tests and confirm pass.
6. Run stub scan + build gate + test gate.
7. Set all 6 to `complete`.
8. Set all 6 to `verified` only if linked mapped tests also pass (`1953` is linked); otherwise keep linked feature at `complete` with blocker note.
9. Run checkpoint protocol and commit.

---

### Task 12: Port/Resolve Batch 5 Mapped Tests (11 tests)

**Files:**

- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamBatchingTests.cs` (`T:742`)
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/NatsConsumerTests.cs` (`T:1304`)
- Create/Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamEngineTests.cs` (`T:1476,1606,1694,1696,1708,1757,1767,1777`)
- Create/Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server/MqttHandlerTests.cs` (`T:2272`)
- Modify: `porting.db`

**Per-test loop (REQUIRED):**

1. Read exact Go test body (`test show <id>` + source lines).
2. Attempt faithful C# port.
3. Run single-test filter and collect output.
4. If pass: mark test `verified`.
5. If blocked by infra: keep `deferred` with specific reason; do not fake-pass.

Single-test run template:

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~<ClassName>.<MethodName>" --verbosity normal
```

Status updates (max 15 IDs):

- Verified chunk example:

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  test batch-update --ids "742,1304,1476,1606,1694,1696,1708,1757,1767,1777,2272" \
  --set-status verified --db porting.db --execute
```

- Deferred (if blocked) per-test with reason:

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  test update <id> --status deferred --db porting.db \
  --override "blocked: requires running JetStream/MQTT server harness parity"
```

Checkpoint after each test class and one commit at task end.

---

### Task 13: Batch 5 Final Verification and Closure

**Files:**

- Modify: `porting.db`
- Generate: `reports/current.md`

**Step 1: Full gates**

```bash
dotnet build dotnet/
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.IntegrationTests/ --verbosity normal
```

**Step 2: Batch-level audit checks**

```bash
dotnet run --project tools/NatsNet.PortTracker -- audit --type features --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- audit --type tests --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- batch show 5 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
```

**Step 3: Global stub scan for touched areas**

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

**Step 4: Complete batch only if all items satisfy allowed terminal states**

```bash
dotnet run --project tools/NatsNet.PortTracker -- batch complete 5 --db porting.db
```

If blocked by deferred tests/features, do not force completion; leave explicit blocker notes.

**Step 5: Generate report + commit**

```bash
./reports/generate-report.sh
git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server \
        tools/generate-jetstream-errors.sh \
        porting.db reports/
git commit -m "feat(batch5): port jetstream error constructors and verify mapped tests"
```
