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

18 KiB
Raw Permalink Blame History

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

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

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

  1. Run full build:
    /usr/local/share/dotnet/dotnet build dotnet/
    
  2. Run full unit tests:
    /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:
    /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

/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

  • 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

/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, 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

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

  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?