Files
natsnet/docs/plans/2026-02-27-batch-4-logging-plan.md
Joseph Doherty b928be4f2f Add batch plans for batches 1-5 and 8 (rounds 1-3)
Generated design docs and implementation plans via Codex for:
- Batch 1: Proto, Const, CipherSuites, NKey, JWT
- Batch 2: Parser, Sublist, MemStore remainders
- Batch 3: SendQ, Service, Client ProxyProto
- Batch 4: Logging
- Batch 5: JetStream Errors
- Batch 8: Store Interfaces

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

507 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Batch 4 (Logging) Implementation Plan
> **For Codex:** REQUIRED SUB-SKILL: Use `executeplan` to implement this plan task-by-task.
**Goal:** Implement and verify Batch 4 logging parity (`11` features, `31` tests) from `server/log.go` with evidence-backed status updates and zero stub leakage.
**Architecture:** Add a dedicated `NatsServer` logging partial that ports the mapped `log.go` methods while preserving existing `ILogger`-based call sites. Implement in two feature groups (<=20 each), then port mapped tests in three class-based groups with strict per-feature and per-test verification loops. Use deferred-with-reason only when runtime blockers are proven.
**Tech Stack:** .NET 10, C# latest, xUnit 3, Shouldly, NSubstitute, PortTracker CLI, SQLite (`porting.db`)
**Design doc:** `docs/plans/2026-02-27-batch-4-logging-design.md`
---
## Batch 4 Working Set
Batch facts:
- Batch ID: `4`
- Features: `11`
- Tests: `31`
- Dependency: `Batch 1`
- Go file: `server/log.go`
Feature groups (max group size <= 20):
- **F1 Core Logger Wiring (5):** `2050,2052,2053,2054,2067`
- **F2 Error + Rate-Limit Helpers (6):** `2057,2058,2059,2061,2062,2063`
Test groups:
- **T1 Gateway + Route (11):** `622,623,643,678,2820,2826,2827,2828,2834,2847,2848`
- **T2 Leaf + MQTT (15):** `1906,1911,1916,1917,1922,1940,1947,1954,1971,1973,1977,1991,2000,2188,2270`
- **T3 Concurrency + WebSocket (5):** `2469,2506,3104,3110,3130`
Environment note:
- `dotnet` is not on PATH in this environment; use `/usr/local/share/dotnet/dotnet` in commands.
---
## MANDATORY VERIFICATION PROTOCOL
> **NON-NEGOTIABLE:** Every feature and every test in this plan must follow this protocol.
### Per-Feature Verification Loop (REQUIRED for each feature ID)
1. Read Go source mapping and intent:
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- feature show <id> --db porting.db
```
2. Read the mapped `server/log.go` code region for the feature.
3. Write C# implementation for only that features behavior.
4. Build immediately:
```bash
/usr/local/share/dotnet/dotnet build dotnet/
```
5. Run related tests for the affected area (focused class/method filter).
6. Add the feature ID to a verified-candidates list only after build + related tests are green.
### Per-Test Verification Loop (REQUIRED for each test ID)
1. Read test mapping:
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- test show <id> --db porting.db
```
2. Read Go test method lines and identify expected logging behavior.
3. Write/replace C# test with real Arrange/Act/Assert.
4. Run only that test and confirm discovery + pass:
```bash
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
--filter "FullyQualifiedName~<ExactTestMethod>" --verbosity normal
```
5. Add test ID to verified-candidates list only after focused test passes.
### Stub Detection Check (REQUIRED after each feature group and each test class group)
Run these checks on touched files before any status promotion:
```bash
# 1) Forbidden stub markers
grep -n -E "(NotImplementedException|TODO|PLACEHOLDER)" \
dotnet/src/ZB.MOM.NatsNet.Server/NatsServer*.cs \
dotnet/src/ZB.MOM.NatsNet.Server/Internal/NatsLogger.cs \
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/*.cs \
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/*.cs \
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server/*.cs
# 2) Empty method bodies in changed C# files
for f in $(git diff --name-only -- '*.cs'); do
grep -n -E "^\s*(public|private|internal|protected).*\)\s*\{\s*\}\s*$" "$f";
done
```
Any match blocks status updates until fixed or explicitly deferred with reason.
### Build Gate (REQUIRED after each feature group)
```bash
/usr/local/share/dotnet/dotnet build dotnet/
```
Required result: build succeeds with zero errors.
### Test Gate (REQUIRED before marking any Batch 4 feature as `verified`)
Run all related suites for the currently active groups and require `Failed: 0`:
```bash
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
--filter "FullyQualifiedName~NatsLoggerTests|FullyQualifiedName~ServerLoggerTests" --verbosity normal
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
--filter "FullyQualifiedName~GatewayHandlerTests|FullyQualifiedName~RouteHandlerTests" --verbosity normal
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
--filter "FullyQualifiedName~LeafNodeHandlerTests|FullyQualifiedName~MqttHandlerTests" --verbosity normal
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
--filter "FullyQualifiedName~ConcurrencyTests1|FullyQualifiedName~ConcurrencyTests2|FullyQualifiedName~WebSocketHandlerTests" --verbosity normal
```
Rule: do not mark any feature `verified` until all related mapped tests for that feature group are passing. If blocked, keep feature at `complete` and defer blocked tests with explicit reason.
### Status Update Protocol (REQUIRED)
- Max `15` IDs per `feature batch-update` or `test batch-update` command.
- Evidence required for each update chunk:
- Go source reviewed
- build gate output
- related focused test output
- stub detection output
- Required state progression:
- Features: `deferred/not_started -> stub -> complete -> verified`
- Tests: `deferred/not_started -> stub -> verified` (or remain `deferred` with reason)
Command templates:
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature batch-update --ids "<max15ids>" --set-status stub --db porting.db --execute
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature batch-update --ids "<max15ids>" --set-status complete --db porting.db --execute
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature batch-update --ids "<max15ids>" --set-status verified --db porting.db --execute
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
test batch-update --ids "<max15ids>" --set-status stub --db porting.db --execute
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
test batch-update --ids "<max15ids>" --set-status verified --db porting.db --execute
```
If audit disagrees, attach override evidence:
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature update <id> --status <status> --db porting.db --override "verification evidence: <reason>"
```
### Checkpoint Protocol Between Tasks (REQUIRED)
After each task, before starting the next:
1. Run full build:
```bash
/usr/local/share/dotnet/dotnet build dotnet/
```
2. Run full unit tests:
```bash
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal
```
3. Record pass/fail totals.
4. Commit the completed task slice (including `porting.db`) before proceeding.
---
## ANTI-STUB GUARDRAILS (NON-NEGOTIABLE)
### Forbidden Patterns
Do not introduce these in feature or test code:
- `throw new NotImplementedException(...)`
- `TODO` / `PLACEHOLDER` markers in newly touched Batch 4 code
- Empty method bodies (`{ }`) for mapped feature methods
- Trivial always-pass assertions (`Assert.True(true)`, `Assert.Pass()`)
- Non-behavioral string/self checks used in place of production behavior
- Tests that never invoke production code
### Hard Limits
- Max `20` features per feature group.
- Max `15` IDs per status update command.
- Max `1` feature group status promotion per verification cycle.
- Mandatory build gate + related test gate before any `verified` promotion.
- Mandatory checkpoint commit between tasks.
### If You Get Stuck (REQUIRED BEHAVIOR)
Do not stub. Do not fake-pass.
1. Keep the blocked item `deferred`.
2. Add explicit reason with `--override`:
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature update <id> --status deferred --db porting.db \
--override "blocked: <specific runtime/dependency reason>"
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
test update <id> --status deferred --db porting.db \
--override "blocked: <specific runtime/dependency reason>"
```
3. Commit only proven work and continue with next unblocked ID.
---
### Task 1: Preflight and Batch Claim
**Files:**
- Modify: `porting.db`
**Step 1: Confirm dependency and batch readiness**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 1 --db porting.db
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 4 --db porting.db
```
**Step 2: Start batch 4**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch start 4 --db porting.db
```
**Step 3: Mark F1 as `stub`**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature batch-update --ids "2050,2052,2053,2054,2067" --set-status stub --db porting.db --execute
```
**Step 4: Checkpoint protocol + commit**
---
### Task 2: Implement Feature Group F1 (Core Logger Wiring)
**Files:**
- Create: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Logging.cs`
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.cs`
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Internal/NatsLogger.cs`
- Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/NatsLoggerTests.cs`
- Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server/ServerLifecycleStubFeaturesTests.cs` (or dedicated new server logging test file if cleaner)
- Modify: `porting.db`
**Step 1: Write/expand failing tests for F1 mapped behaviors**
- `ConfigureLogger` option precedence behavior
- `SetLogger` delegates to `SetLoggerV2`
- `SetLoggerV2` flag + replacement semantics
- `ReOpenLogFile` behavior by log mode
- `ExecuteLogCall` no-op with nil logger
**Step 2: Run focused tests and confirm they fail first**
```bash
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
--filter "FullyQualifiedName~NatsLoggerTests|FullyQualifiedName~ServerLoggerTests" --verbosity normal
```
**Step 3: Implement F1 in `NatsServer.Logging.cs` with Go parity**
**Step 4: Run per-feature verification loop for `2050,2052,2053,2054,2067`**
**Step 5: Run stub detection check + build gate + focused test gate**
**Step 6: Promote F1 statuses to `complete` then `verified`**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature batch-update --ids "2050,2052,2053,2054,2067" --set-status complete --db porting.db --execute
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature batch-update --ids "2050,2052,2053,2054,2067" --set-status verified --db porting.db --execute
```
**Step 7: Checkpoint protocol + commit**
---
### Task 3: Implement Feature Group F2 (Errors + Rate-Limit Helpers)
**Files:**
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Logging.cs`
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.cs`
- Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/NatsLoggerTests.cs`
- Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server/ServerLifecycleStubFeaturesTests.cs` (or dedicated server logging test file)
- Modify: `porting.db`
**Step 1: Mark F2 as `stub`**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature batch-update --ids "2057,2058,2059,2061,2062,2063" --set-status stub --db porting.db --execute
```
**Step 2: Write/expand failing tests for F2**
- `Errors`, `Errorc`, `Errorsc` formatting parity
- `RateLimitFormatWarnf` dedupe-by-format
- `RateLimitWarnf` dedupe-by-rendered-statement
- `RateLimitDebugf` respects debug flag and dedupe
**Step 3: Run focused tests and confirm fail**
```bash
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
--filter "FullyQualifiedName~NatsLoggerTests|FullyQualifiedName~ServerLoggerTests" --verbosity normal
```
**Step 4: Implement F2 feature methods**
**Step 5: Run per-feature verification loop for `2057,2058,2059,2061,2062,2063`**
**Step 6: Run stub detection + build gate + focused test gate**
**Step 7: Promote F2 statuses to `complete` then `verified`**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature batch-update --ids "2057,2058,2059,2061,2062,2063" --set-status complete --db porting.db --execute
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
feature batch-update --ids "2057,2058,2059,2061,2062,2063" --set-status verified --db porting.db --execute
```
**Step 8: Checkpoint protocol + commit**
---
### Task 4: Port Test Group T1 (Gateway + Route, 11 tests)
**Files:**
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/GatewayHandlerTests.Impltests.cs`
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs`
- Modify: `porting.db`
**Step 1: Mark T1 tests as `stub`**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
test batch-update --ids "622,623,643,678,2820,2826,2827,2828,2834,2847,2848" \
--set-status stub --db porting.db --execute
```
**Step 2: For each test ID, run Per-Test Verification Loop**
**Step 3: Run class-level gates**
```bash
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
--filter "FullyQualifiedName~GatewayHandlerTests|FullyQualifiedName~RouteHandlerTests" --verbosity normal
```
**Step 4: Run stub detection for touched backlog files**
**Step 5: Promote T1 test IDs to `verified`**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
test batch-update --ids "622,623,643,678,2820,2826,2827,2828,2834,2847,2848" \
--set-status verified --db porting.db --execute
```
**Step 6: Checkpoint protocol + commit**
---
### Task 5: Port Test Group T2 (Leaf + MQTT, 15 tests)
**Files:**
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/LeafNodeHandlerTests.Impltests.cs`
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/MqttHandlerTests.Impltests.cs`
- Modify: `porting.db`
**Step 1: Mark T2 tests as `stub`**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
test batch-update --ids "1906,1911,1916,1917,1922,1940,1947,1954,1971,1973,1977,1991,2000,2188,2270" \
--set-status stub --db porting.db --execute
```
**Step 2: Run Per-Test Verification Loop for each T2 ID**
**Step 3: Run class-level gates**
```bash
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
--filter "FullyQualifiedName~LeafNodeHandlerTests|FullyQualifiedName~MqttHandlerTests" --verbosity normal
```
**Step 4: Run stub detection for touched backlog files**
**Step 5: Promote T2 test IDs in max-15 chunks**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
test batch-update --ids "1906,1911,1916,1917,1922,1940,1947,1954,1971,1973,1977,1991,2000,2188,2270" \
--set-status verified --db porting.db --execute
```
**Step 6: Checkpoint protocol + commit**
---
### Task 6: Port Test Group T3 (Concurrency + WebSocket, 5 tests)
**Files:**
- 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/WebSocketHandlerTests.Impltests.cs`
- Modify: `porting.db`
**Step 1: Mark T3 tests as `stub`**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
test batch-update --ids "2469,2506,3104,3110,3130" --set-status stub --db porting.db --execute
```
**Step 2: Run Per-Test Verification Loop for each T3 ID**
**Step 3: Run class-level gates**
```bash
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
--filter "FullyQualifiedName~ConcurrencyTests1|FullyQualifiedName~ConcurrencyTests2|FullyQualifiedName~WebSocketHandlerTests" \
--verbosity normal
```
**Step 4: Run stub detection for touched backlog files**
**Step 5: Promote T3 test IDs to `verified`**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
test batch-update --ids "2469,2506,3104,3110,3130" --set-status verified --db porting.db --execute
```
**Step 6: Checkpoint protocol + commit**
---
### Task 7: Batch 4 Closure and Final Verification
**Files:**
- Modify: `porting.db`
- Optional: `reports/current.md` (if report regenerated)
**Step 1: Run final full verification gates**
```bash
/usr/local/share/dotnet/dotnet build dotnet/
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.IntegrationTests/ --verbosity normal
```
**Step 2: Validate batch state**
```bash
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 4 --db porting.db
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch complete 4 --db porting.db
```
**Step 3: Generate status report**
```bash
./reports/generate-report.sh
```
**Step 4: Final checkpoint commit**
```bash
git add dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests porting.db reports/current.md
git commit -m "feat(batch4): implement logging features and mapped tests with verification evidence"
```
---
Plan complete and saved to `docs/plans/2026-02-27-batch-4-logging-plan.md`. Two execution options:
1. Subagent-Driven (this session) - dispatch a fresh subagent per task, review between tasks, fast iteration.
2. Parallel Session (separate) - open a new session with `executeplan`, batch execution with checkpoints.
Which approach?