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.
18 KiB
Batch 4 (Logging) Implementation Plan
For Codex: REQUIRED SUB-SKILL: Use
executeplanto 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:
dotnetis not on PATH in this environment; use/usr/local/share/dotnet/dotnetin 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)
- Read Go source mapping and intent:
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- feature show <id> --db porting.db - Read the mapped
server/log.gocode region for the feature. - Write C# implementation for only that feature’s behavior.
- Build immediately:
/usr/local/share/dotnet/dotnet build dotnet/ - Run related tests for the affected area (focused class/method filter).
- 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)
- Read test mapping:
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- test show <id> --db porting.db - Read Go test method lines and identify expected logging behavior.
- Write/replace C# test with real Arrange/Act/Assert.
- Run only that test and confirm discovery + pass:
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~<ExactTestMethod>" --verbosity normal - 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:
# 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)
/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:
/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
15IDs perfeature batch-updateortest batch-updatecommand. - 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 remaindeferredwith reason)
- Features:
Command templates:
/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:
/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:
- Run full build:
/usr/local/share/dotnet/dotnet build dotnet/ - Run full unit tests:
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal - Record pass/fail totals.
- 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/PLACEHOLDERmarkers 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
20features per feature group. - Max
15IDs per status update command. - Max
1feature group status promotion per verification cycle. - Mandatory build gate + related test gate before any
verifiedpromotion. - Mandatory checkpoint commit between tasks.
If You Get Stuck (REQUIRED BEHAVIOR)
Do not stub. Do not fake-pass.
- Keep the blocked item
deferred. - Add explicit reason with
--override:/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>" - 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
/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
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch start 4 --db porting.db
Step 3: Mark F1 as stub
/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
ConfigureLoggeroption precedence behaviorSetLoggerdelegates toSetLoggerV2SetLoggerV2flag + replacement semanticsReOpenLogFilebehavior by log modeExecuteLogCallno-op with nil logger
Step 2: Run focused tests and confirm they fail first
/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
/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
/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,Errorscformatting parityRateLimitFormatWarnfdedupe-by-formatRateLimitWarnfdedupe-by-rendered-statementRateLimitDebugfrespects debug flag and dedupe
Step 3: Run focused tests and confirm fail
/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
/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
/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
/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
/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
/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
/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
/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
/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
/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
/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
/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
/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
./reports/generate-report.sh
Step 4: Final checkpoint commit
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:
- Subagent-Driven (this session) - dispatch a fresh subagent per task, review between tasks, fast iteration.
- Parallel Session (separate) - open a new session with
executeplan, batch execution with checkpoints.
Which approach?