diff --git a/docs/plans/2026-02-23-nats-post-strict-full-go-parity-plan.md b/docs/plans/2026-02-23-nats-post-strict-full-go-parity-plan.md new file mode 100644 index 0000000..d622fe0 --- /dev/null +++ b/docs/plans/2026-02-23-nats-post-strict-full-go-parity-plan.md @@ -0,0 +1,794 @@ +# NATS Post-Strict Full Go Parity Implementation Plan + +> **For Codex:** REQUIRED SUB-SKILL: Use `executeplan` to implement this plan task-by-task. + +**Goal:** Close all remaining behavior-level NATS parity gaps versus local Go HEAD by porting missing functionality to .NET with contract-complete tests and synchronized parity documentation. + +**Architecture:** Execute in strict dependency waves: parity inventory guardrails first, then protocol/inter-server semantics, then MQTT depth, then JetStream runtime/storage/RAFT/cluster governance, then operational/config/runtime parity and docs synchronization. Each capability row closes only on Behavior + Tests + Docs evidence. + +**Tech Stack:** .NET 10, C# 14, xUnit 3, Shouldly, System.IO.Pipelines, ASP.NET Core monitor endpoints, socket integration fixtures, JetStream/RAFT internals. + +--- + +**Execution guardrails** +- Use `@test-driven-development` in every task. +- Switch to `@systematic-debugging` when runtime behavior diverges from expected protocol/state contracts. +- One commit per task. +- Run `@verification-before-completion` before final parity closure claims. + +### Task 1: Add Go-HEAD Capability Inventory and Coverage Guardrail + +**Files:** +- Create: `docs/plans/2026-02-23-nats-post-strict-full-go-parity-map.md` +- Create: `tests/NATS.Server.Tests/Parity/GoHeadCapabilityInventoryTests.cs` +- Create: `tests/NATS.Server.Tests/Parity/GoHeadCapabilityInventory.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public void Go_head_capability_inventory_requires_behavior_tests_and_docs_columns() +{ + var report = GoHeadCapabilityInventory.Load( + "docs/plans/2026-02-23-nats-post-strict-full-go-parity-map.md"); + report.InvalidRows.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~GoHeadCapabilityInventoryTests" -v minimal` +Expected: FAIL because inventory map and parser are not yet present. + +**Step 3: Write minimal implementation** + +```csharp +public sealed record CapabilityRow(string Capability, string Behavior, string Tests, string Docs); +public IReadOnlyList InvalidRows => + Rows.Where(r => r.Behavior == "done" && (r.Tests != "done" || r.Docs != "closed")).ToArray(); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~GoHeadCapabilityInventoryTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add docs/plans/2026-02-23-nats-post-strict-full-go-parity-map.md tests/NATS.Server.Tests/Parity/GoHeadCapabilityInventoryTests.cs tests/NATS.Server.Tests/Parity/GoHeadCapabilityInventory.cs +git commit -m "test: add go-head capability inventory parity guardrail" +``` + +### Task 2: Expand Parity Contradiction Detection Beyond JetStream Truth Matrix + +**Files:** +- Modify: `tests/NATS.Server.Tests/Parity/JetStreamParityTruthMatrix.cs` +- Create: `tests/NATS.Server.Tests/Parity/NatsParityContradictionScanner.cs` +- Create: `tests/NATS.Server.Tests/Parity/NatsParityContradictionTests.cs` +- Modify: `tests/NATS.Server.Tests/DifferencesParityClosureTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public void Differences_notes_have_no_negative_claims_against_closed_capability_rows() +{ + var report = NatsParityContradictionScanner.Scan( + "differences.md", + "docs/plans/2026-02-23-nats-post-strict-full-go-parity-map.md"); + report.Contradictions.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~NatsParityContradictionTests|FullyQualifiedName~DifferencesParityClosureTests" -v minimal` +Expected: FAIL until scanner and docs alignment are implemented. + +**Step 3: Write minimal implementation** + +```csharp +if (line.Contains("remain", StringComparison.OrdinalIgnoreCase) && closedCapabilityTokens.Any(t => line.Contains(t))) + contradictions.Add(line); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~NatsParityContradictionTests|FullyQualifiedName~DifferencesParityClosureTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add tests/NATS.Server.Tests/Parity/JetStreamParityTruthMatrix.cs tests/NATS.Server.Tests/Parity/NatsParityContradictionScanner.cs tests/NATS.Server.Tests/Parity/NatsParityContradictionTests.cs tests/NATS.Server.Tests/DifferencesParityClosureTests.cs +git commit -m "test: add full nats parity contradiction scanner" +``` + +### Task 3: Complete Deep Account-Scoped Inter-Server Delivery Semantics + +**Files:** +- Modify: `src/NATS.Server/NatsServer.cs` +- Modify: `src/NATS.Server/Auth/Account.cs` +- Modify: `src/NATS.Server/Subscriptions/SubList.cs` +- Test: `tests/NATS.Server.Tests/Routes/RouteDeepAccountScopeParityTests.cs` +- Test: `tests/NATS.Server.Tests/Gateways/GatewayDeepAccountScopeParityTests.cs` +- Test: `tests/NATS.Server.Tests/LeafNodes/LeafDeepAccountScopeParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Remote_delivery_preserves_account_scope_under_multi_account_overlap_and_reconnect() +{ + await using var fx = await DeepAccountScopeFixture.StartAsync(); + var result = await fx.RunOverlapScenarioAsync(); + result.CrossAccountLeakDetected.ShouldBeFalse(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~DeepAccountScopeParityTests" -v minimal` +Expected: FAIL due missing deep account-scoped routing behavior in edge paths. + +**Step 3: Write minimal implementation** + +```csharp +var account = GetOrCreateAccount(message.Account); +var matches = account.SubList.Match(subject); +DeliverMatches(matches, account, subject, replyTo, payload); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~DeepAccountScopeParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/NatsServer.cs src/NATS.Server/Auth/Account.cs src/NATS.Server/Subscriptions/SubList.cs tests/NATS.Server.Tests/Routes/RouteDeepAccountScopeParityTests.cs tests/NATS.Server.Tests/Gateways/GatewayDeepAccountScopeParityTests.cs tests/NATS.Server.Tests/LeafNodes/LeafDeepAccountScopeParityTests.cs +git commit -m "feat: complete deep account-scoped inter-server delivery semantics" +``` + +### Task 4: Complete Route/Gateway/Leaf Advanced Interest and Topology Contracts + +**Files:** +- Modify: `src/NATS.Server/Routes/RouteConnection.cs` +- Modify: `src/NATS.Server/Routes/RouteManager.cs` +- Modify: `src/NATS.Server/Gateways/GatewayConnection.cs` +- Modify: `src/NATS.Server/Gateways/GatewayManager.cs` +- Modify: `src/NATS.Server/LeafNodes/LeafConnection.cs` +- Modify: `src/NATS.Server/LeafNodes/LeafNodeManager.cs` +- Test: `tests/NATS.Server.Tests/Routes/RouteAdvancedInterestTopologyTests.cs` +- Test: `tests/NATS.Server.Tests/Gateways/GatewayAdvancedInterestTopologyTests.cs` +- Test: `tests/NATS.Server.Tests/LeafNodes/LeafAdvancedInterestTopologyTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Interest_replay_topology_gossip_and_disconnect_rejoin_preserve_consistent_remote_interest_state() +{ + await using var fx = await InterServerTopologyFixture.StartAsync(); + var report = await fx.RunConvergenceScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~AdvancedInterestTopologyTests" -v minimal` +Expected: FAIL because deep convergence behaviors are incomplete. + +**Step 3: Write minimal implementation** + +```csharp +// Reconcile on reconnect: replay canonical remote-interest snapshot keyed by peer/account/subject/queue. +ApplyRemoteInterestSnapshot(peerId, snapshotRows); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~AdvancedInterestTopologyTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/Routes/RouteConnection.cs src/NATS.Server/Routes/RouteManager.cs src/NATS.Server/Gateways/GatewayConnection.cs src/NATS.Server/Gateways/GatewayManager.cs src/NATS.Server/LeafNodes/LeafConnection.cs src/NATS.Server/LeafNodes/LeafNodeManager.cs tests/NATS.Server.Tests/Routes/RouteAdvancedInterestTopologyTests.cs tests/NATS.Server.Tests/Gateways/GatewayAdvancedInterestTopologyTests.cs tests/NATS.Server.Tests/LeafNodes/LeafAdvancedInterestTopologyTests.cs +git commit -m "feat: complete advanced inter-server interest and topology contracts" +``` + +### Task 5: Expand MQTT Control Packet Runtime Semantics + +**Files:** +- Modify: `src/NATS.Server/Mqtt/MqttPacketReader.cs` +- Modify: `src/NATS.Server/Mqtt/MqttPacketWriter.cs` +- Modify: `src/NATS.Server/Mqtt/MqttProtocolParser.cs` +- Modify: `src/NATS.Server/Mqtt/MqttConnection.cs` +- Test: `tests/NATS.Server.Tests/Mqtt/MqttControlPacketParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public void Subscribe_ping_disconnect_and_connack_flags_follow_control_packet_contract() +{ + var report = MqttControlPacketFixture.Run(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttControlPacketParityTests" -v minimal` +Expected: FAIL until full control packet handling is implemented. + +**Step 3: Write minimal implementation** + +```csharp +switch (packet.Type) +{ + case MqttControlPacketType.PingReq: await SendPingRespAsync(ct); break; + case MqttControlPacketType.Disconnect: return; +} +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttControlPacketParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/Mqtt/MqttPacketReader.cs src/NATS.Server/Mqtt/MqttPacketWriter.cs src/NATS.Server/Mqtt/MqttProtocolParser.cs src/NATS.Server/Mqtt/MqttConnection.cs tests/NATS.Server.Tests/Mqtt/MqttControlPacketParityTests.cs +git commit -m "feat: expand mqtt control packet runtime parity" +``` + +### Task 6: Add MQTT QoS2 and Session-State Recovery Contracts + +**Files:** +- Modify: `src/NATS.Server/Mqtt/MqttConnection.cs` +- Modify: `src/NATS.Server/Mqtt/MqttListener.cs` +- Test: `tests/NATS.Server.Tests/Mqtt/MqttQos2ParityTests.cs` +- Test: `tests/NATS.Server.Tests/Mqtt/MqttSessionRecoveryParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Qos2_flow_and_session_reconnect_recovery_follow_publish_release_complete_contract() +{ + await using var fx = await MqttQos2Fixture.StartAsync(); + var report = await fx.RunQos2ScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttQos2ParityTests|FullyQualifiedName~MqttSessionRecoveryParityTests" -v minimal` +Expected: FAIL because QoS2 handshake/recovery semantics are missing. + +**Step 3: Write minimal implementation** + +```csharp +// Track QoS2 states: Received -> Released -> Completed by packet id. +_qos2State[packetId] = Qos2State.Received; +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttQos2ParityTests|FullyQualifiedName~MqttSessionRecoveryParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/Mqtt/MqttConnection.cs src/NATS.Server/Mqtt/MqttListener.cs tests/NATS.Server.Tests/Mqtt/MqttQos2ParityTests.cs tests/NATS.Server.Tests/Mqtt/MqttSessionRecoveryParityTests.cs +git commit -m "feat: implement mqtt qos2 and session recovery parity" +``` + +### Task 7: Complete MQTT-to-Account/JetStream Integration Semantics + +**Files:** +- Modify: `src/NATS.Server/NatsServer.cs` +- Modify: `src/NATS.Server/Mqtt/MqttListener.cs` +- Modify: `src/NATS.Server/Mqtt/MqttConnection.cs` +- Modify: `src/NATS.Server/JetStream/StreamManager.cs` +- Test: `tests/NATS.Server.Tests/Mqtt/MqttAccountJetStreamParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Mqtt_publish_subscribe_paths_apply_account_permissions_and_jetstream_persistence_contracts() +{ + await using var fx = await MqttAccountJetStreamFixture.StartAsync(); + var report = await fx.RunScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttAccountJetStreamParityTests" -v minimal` +Expected: FAIL until MQTT paths fully enforce account + storage contracts. + +**Step 3: Write minimal implementation** + +```csharp +if (!account.IsPublishAllowed(topic)) + return MqttError.NotAuthorized; +_ = _jetStreamPublisher?.TryCapture(topic, payload); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttAccountJetStreamParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/NatsServer.cs src/NATS.Server/Mqtt/MqttListener.cs src/NATS.Server/Mqtt/MqttConnection.cs src/NATS.Server/JetStream/StreamManager.cs tests/NATS.Server.Tests/Mqtt/MqttAccountJetStreamParityTests.cs +git commit -m "feat: complete mqtt account and jetstream integration semantics" +``` + +### Task 8: Deepen JetStream Service Lifecycle and Internal Client Contracts + +**Files:** +- Modify: `src/NATS.Server/JetStream/JetStreamService.cs` +- Modify: `src/NATS.Server/NatsServer.cs` +- Test: `tests/NATS.Server.Tests/JetStream/JetStreamServiceLifecycleParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Jetstream_service_start_stop_reconfigure_and_internal_client_contracts_are_lifecycle_safe() +{ + await using var fx = await JetStreamLifecycleFixture.StartAsync(); + var report = await fx.RunLifecycleScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamServiceLifecycleParityTests" -v minimal` +Expected: FAIL due minimal JetStreamService lifecycle behavior. + +**Step 3: Write minimal implementation** + +```csharp +public Task ReloadAsync(JetStreamOptions next, CancellationToken ct) { _options = next; return ReconcileAsync(ct); } +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamServiceLifecycleParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/JetStream/JetStreamService.cs src/NATS.Server/NatsServer.cs tests/NATS.Server.Tests/JetStream/JetStreamServiceLifecycleParityTests.cs +git commit -m "feat: deepen jetstream service lifecycle and internal client parity" +``` + +### Task 9: Complete JetStream Stream Runtime Edge Contracts + +**Files:** +- Modify: `src/NATS.Server/JetStream/StreamManager.cs` +- Modify: `src/NATS.Server/JetStream/Publish/JetStreamPublisher.cs` +- Modify: `src/NATS.Server/JetStream/Publish/PublishPreconditions.cs` +- Test: `tests/NATS.Server.Tests/JetStream/JetStreamStreamRuntimeDeepParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Stream_runtime_contracts_hold_for_retention_limit_rollup_dedupe_and_expected_headers_under_long_run_load() +{ + await using var fx = await StreamRuntimeDeepFixture.StartAsync(); + var report = await fx.RunLongScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamStreamRuntimeDeepParityTests" -v minimal` +Expected: FAIL while deep edge contracts remain incomplete. + +**Step 3: Write minimal implementation** + +```csharp +if (!preconditions.ValidateExpectedLastPerSubject(...)) return PubAck.Error(10071); +ApplyRetentionAndRollupConstraints(stream, publishRequest); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamStreamRuntimeDeepParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/JetStream/StreamManager.cs src/NATS.Server/JetStream/Publish/JetStreamPublisher.cs src/NATS.Server/JetStream/Publish/PublishPreconditions.cs tests/NATS.Server.Tests/JetStream/JetStreamStreamRuntimeDeepParityTests.cs +git commit -m "feat: complete deep jetstream stream runtime parity contracts" +``` + +### Task 10: Complete JetStream Consumer State-Machine Edge Contracts + +**Files:** +- Modify: `src/NATS.Server/JetStream/ConsumerManager.cs` +- Modify: `src/NATS.Server/JetStream/Consumers/AckProcessor.cs` +- Modify: `src/NATS.Server/JetStream/Consumers/PullConsumerEngine.cs` +- Modify: `src/NATS.Server/JetStream/Consumers/PushConsumerEngine.cs` +- Test: `tests/NATS.Server.Tests/JetStream/JetStreamConsumerDeepStateMachineParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Consumer_state_machine_preserves_cursor_ack_floor_redelivery_backoff_and_flow_across_restart_cycles() +{ + await using var fx = await ConsumerDeepStateFixture.StartAsync(); + var report = await fx.RunScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamConsumerDeepStateMachineParityTests" -v minimal` +Expected: FAIL until deep state-machine semantics are implemented. + +**Step 3: Write minimal implementation** + +```csharp +if (ackPolicy == AckPolicy.All) AdvanceAckFloor(seq); +if (deliveryAttempt > maxDeliver) MoveToTerminalState(seq); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamConsumerDeepStateMachineParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/JetStream/ConsumerManager.cs src/NATS.Server/JetStream/Consumers/AckProcessor.cs src/NATS.Server/JetStream/Consumers/PullConsumerEngine.cs src/NATS.Server/JetStream/Consumers/PushConsumerEngine.cs tests/NATS.Server.Tests/JetStream/JetStreamConsumerDeepStateMachineParityTests.cs +git commit -m "feat: complete deep jetstream consumer state-machine parity" +``` + +### Task 11: Deepen Mirror/Source Multi-Source and Cross-Account Recovery Semantics + +**Files:** +- Modify: `src/NATS.Server/JetStream/StreamManager.cs` +- Modify: `src/NATS.Server/JetStream/MirrorSource/MirrorCoordinator.cs` +- Modify: `src/NATS.Server/JetStream/MirrorSource/SourceCoordinator.cs` +- Test: `tests/NATS.Server.Tests/JetStream/JetStreamMirrorSourceDeepParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Mirror_source_fanin_and_cross_account_recovery_preserve_ordering_and_filter_contracts() +{ + await using var fx = await MirrorSourceDeepFixture.StartAsync(); + var report = await fx.RunRecoveryScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamMirrorSourceDeepParityTests" -v minimal` +Expected: FAIL for multi-source recovery and ordering edge cases. + +**Step 3: Write minimal implementation** + +```csharp +var ordered = pendingReplications.OrderBy(e => e.Sequence); +foreach (var entry in ordered) ApplyReplication(entry); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamMirrorSourceDeepParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/JetStream/StreamManager.cs src/NATS.Server/JetStream/MirrorSource/MirrorCoordinator.cs src/NATS.Server/JetStream/MirrorSource/SourceCoordinator.cs tests/NATS.Server.Tests/JetStream/JetStreamMirrorSourceDeepParityTests.cs +git commit -m "feat: deepen jetstream mirror source recovery and fan-in parity" +``` + +### Task 12: Complete FileStore Deep Durability and Subject-Index Contracts + +**Files:** +- Modify: `src/NATS.Server/JetStream/Storage/FileStore.cs` +- Modify: `src/NATS.Server/JetStream/Storage/FileStoreBlock.cs` +- Modify: `src/NATS.Server/JetStream/Storage/MemStore.cs` +- Test: `tests/NATS.Server.Tests/JetStream/JetStreamFileStoreDeepDurabilityParityTests.cs` +- Test: `tests/NATS.Server.Tests/JetStream/JetStreamStoreSubjectIndexParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Filestore_recovery_and_subject_index_contracts_hold_under_block_rollover_compaction_and_restart() +{ + var report = await FileStoreDeepFixture.RunScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamFileStoreDeepDurabilityParityTests|FullyQualifiedName~JetStreamStoreSubjectIndexParityTests" -v minimal` +Expected: FAIL until deep durability/index semantics are completed. + +**Step 3: Write minimal implementation** + +```csharp +RebuildSubjectIndexFromBlocks(); +ValidateManifestAndReplayGaps(); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamFileStoreDeepDurabilityParityTests|FullyQualifiedName~JetStreamStoreSubjectIndexParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/JetStream/Storage/FileStore.cs src/NATS.Server/JetStream/Storage/FileStoreBlock.cs src/NATS.Server/JetStream/Storage/MemStore.cs tests/NATS.Server.Tests/JetStream/JetStreamFileStoreDeepDurabilityParityTests.cs tests/NATS.Server.Tests/JetStream/JetStreamStoreSubjectIndexParityTests.cs +git commit -m "feat: complete filestore deep durability and subject-index parity" +``` + +### Task 13: Complete RAFT Election/Append/Convergence Deep Runtime Semantics + +**Files:** +- Modify: `src/NATS.Server/Raft/RaftNode.cs` +- Modify: `src/NATS.Server/Raft/RaftReplicator.cs` +- Modify: `src/NATS.Server/Raft/RaftTransport.cs` +- Modify: `src/NATS.Server/Raft/RaftLog.cs` +- Modify: `src/NATS.Server/Raft/RaftSnapshotStore.cs` +- Test: `tests/NATS.Server.Tests/Raft/RaftDeepConsensusParityTests.cs` +- Test: `tests/NATS.Server.Tests/Raft/RaftDeepConvergenceParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Raft_term_vote_append_and_snapshot_convergence_contracts_hold_under_network_partition_and_rejoin() +{ + var report = await RaftDeepFixture.RunPartitionScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~RaftDeepConsensusParityTests|FullyQualifiedName~RaftDeepConvergenceParityTests" -v minimal` +Expected: FAIL for deep partition/rejoin semantics. + +**Step 3: Write minimal implementation** + +```csharp +if (!IsUpToDate(candidateLastTerm, candidateLastIndex)) return VoteResponse.Deny(); +nextIndex[follower] = Math.Max(1, nextIndex[follower] - 1); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~RaftDeepConsensusParityTests|FullyQualifiedName~RaftDeepConvergenceParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/Raft/RaftNode.cs src/NATS.Server/Raft/RaftReplicator.cs src/NATS.Server/Raft/RaftTransport.cs src/NATS.Server/Raft/RaftLog.cs src/NATS.Server/Raft/RaftSnapshotStore.cs tests/NATS.Server.Tests/Raft/RaftDeepConsensusParityTests.cs tests/NATS.Server.Tests/Raft/RaftDeepConvergenceParityTests.cs +git commit -m "feat: complete deep raft consensus and convergence parity" +``` + +### Task 14: Complete JetStream Cluster Governance and Placement Semantics + +**Files:** +- Modify: `src/NATS.Server/JetStream/Cluster/JetStreamMetaGroup.cs` +- Modify: `src/NATS.Server/JetStream/Cluster/StreamReplicaGroup.cs` +- Modify: `src/NATS.Server/JetStream/Cluster/AssetPlacementPlanner.cs` +- Modify: `src/NATS.Server/JetStream/StreamManager.cs` +- Test: `tests/NATS.Server.Tests/JetStream/JetStreamClusterGovernanceDeepParityTests.cs` +- Test: `tests/NATS.Server.Tests/JetStream/JetStreamPlacementDeepParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Meta_and_replica_governance_plus_placement_semantics_reflect_committed_cluster_state() +{ + await using var fx = await JetStreamClusterDeepFixture.StartAsync(); + var report = await fx.RunGovernanceScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamClusterGovernanceDeepParityTests|FullyQualifiedName~JetStreamPlacementDeepParityTests" -v minimal` +Expected: FAIL until governance/placement semantics are deepened. + +**Step 3: Write minimal implementation** + +```csharp +var proposed = _planner.Plan(currentClusterState, streamConfig); +if (!HasPlacementQuorum(proposed)) return PlacementResult.Rejected(); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamClusterGovernanceDeepParityTests|FullyQualifiedName~JetStreamPlacementDeepParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/JetStream/Cluster/JetStreamMetaGroup.cs src/NATS.Server/JetStream/Cluster/StreamReplicaGroup.cs src/NATS.Server/JetStream/Cluster/AssetPlacementPlanner.cs src/NATS.Server/JetStream/StreamManager.cs tests/NATS.Server.Tests/JetStream/JetStreamClusterGovernanceDeepParityTests.cs tests/NATS.Server.Tests/JetStream/JetStreamPlacementDeepParityTests.cs +git commit -m "feat: complete jetstream cluster governance and placement parity" +``` + +### Task 15: Close Advanced Config Surface to Runtime Semantics Drift + +**Files:** +- Modify: `src/NATS.Server/NatsOptions.cs` +- Modify: `src/NATS.Server/Configuration/ConfigProcessor.cs` +- Modify: `src/NATS.Server/Configuration/ConfigReloader.cs` +- Modify: `src/NATS.Server/NatsServer.cs` +- Test: `tests/NATS.Server.Tests/Configuration/ConfigRuntimeSurfaceParityTests.cs` +- Test: `tests/NATS.Server.Tests/Configuration/ConfigReloadRuntimeParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Parsed_config_surface_fields_map_to_runtime_behavior_or_explicitly_rejected_reload_contracts() +{ + var report = await ConfigRuntimeSurfaceFixture.RunAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~ConfigRuntimeSurfaceParityTests|FullyQualifiedName~ConfigReloadRuntimeParityTests" -v minimal` +Expected: FAIL where parsed options do not produce equivalent runtime behavior. + +**Step 3: Write minimal implementation** + +```csharp +if (!RuntimeSupports(optionName)) return ReloadValidation.NonReloadable(optionName); +ApplyRuntimeOption(optionName, value); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~ConfigRuntimeSurfaceParityTests|FullyQualifiedName~ConfigReloadRuntimeParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/NatsOptions.cs src/NATS.Server/Configuration/ConfigProcessor.cs src/NATS.Server/Configuration/ConfigReloader.cs src/NATS.Server/NatsServer.cs tests/NATS.Server.Tests/Configuration/ConfigRuntimeSurfaceParityTests.cs tests/NATS.Server.Tests/Configuration/ConfigReloadRuntimeParityTests.cs +git commit -m "feat: close advanced config surface to runtime parity drift" +``` + +### Task 16: Complete Monitoring/Events Operational Parity Semantics + +**Files:** +- Modify: `src/NATS.Server/Monitoring/MonitorServer.cs` +- Modify: `src/NATS.Server/Monitoring/VarzHandler.cs` +- Modify: `src/NATS.Server/Monitoring/ConnzHandler.cs` +- Modify: `src/NATS.Server/Events/InternalEventSystem.cs` +- Test: `tests/NATS.Server.Tests/Monitoring/MonitoringOperationalParityTests.cs` +- Test: `tests/NATS.Server.Tests/Events/EventSystemOperationalParityTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public async Task Monitoring_and_system_event_operational_contracts_match_runtime_state_under_load() +{ + await using var fx = await OperationalParityFixture.StartAsync(); + var report = await fx.RunScenarioAsync(); + report.InvariantViolations.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MonitoringOperationalParityTests|FullyQualifiedName~EventSystemOperationalParityTests" -v minimal` +Expected: FAIL until operational parity semantics are completed. + +**Step 3: Write minimal implementation** + +```csharp +varz.Events = _eventSystem.BuildRuntimeSummary(); +connz.InterServerScopes = BuildInterServerScopes(); +``` + +**Step 4: Run test to verify it passes** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MonitoringOperationalParityTests|FullyQualifiedName~EventSystemOperationalParityTests" -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add src/NATS.Server/Monitoring/MonitorServer.cs src/NATS.Server/Monitoring/VarzHandler.cs src/NATS.Server/Monitoring/ConnzHandler.cs src/NATS.Server/Events/InternalEventSystem.cs tests/NATS.Server.Tests/Monitoring/MonitoringOperationalParityTests.cs tests/NATS.Server.Tests/Events/EventSystemOperationalParityTests.cs +git commit -m "feat: complete monitoring and event-system operational parity" +``` + +### Task 17: Final Strict Verification and Documentation Synchronization + +**Files:** +- Modify: `differences.md` +- Modify: `docs/plans/2026-02-23-nats-post-strict-full-go-parity-map.md` +- Modify: `docs/plans/2026-02-23-nats-strict-full-go-parity-map.md` +- Modify: `docs/plans/2026-02-23-jetstream-remaining-parity-map.md` +- Modify: `docs/plans/2026-02-23-jetstream-remaining-parity-verification.md` +- Modify: `tests/NATS.Server.Tests/DifferencesParityClosureTests.cs` + +**Step 1: Write the failing test** + +```csharp +[Fact] +public void Differences_and_parity_maps_do_not_claim_closure_without_behavior_and_test_evidence() +{ + var report = NatsParityContradictionScanner.Scan( + "differences.md", + "docs/plans/2026-02-23-nats-post-strict-full-go-parity-map.md"); + report.Contradictions.ShouldBeEmpty(); +} +``` + +**Step 2: Run test to verify it fails** + +Run: `dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~DifferencesParityClosureTests|FullyQualifiedName~NatsParityContradictionTests|FullyQualifiedName~GoHeadCapabilityInventoryTests" -v minimal` +Expected: FAIL until docs are synchronized with implemented capabilities. + +**Step 3: Update docs with exact evidence** + +Run: `rg -n "remain|remaining|incomplete|baseline|stub|placeholder" differences.md docs/plans/2026-02-23-nats-post-strict-full-go-parity-map.md` +Expected: only explicitly deferred items remain, each with blocker rationale. + +**Step 4: Run full verification** + +Run: `dotnet test -v minimal` +Expected: PASS. + +**Step 5: Commit** + +```bash +git add differences.md docs/plans/2026-02-23-nats-post-strict-full-go-parity-map.md docs/plans/2026-02-23-nats-strict-full-go-parity-map.md docs/plans/2026-02-23-jetstream-remaining-parity-map.md docs/plans/2026-02-23-jetstream-remaining-parity-verification.md tests/NATS.Server.Tests/DifferencesParityClosureTests.cs +git commit -m "docs: synchronize post-strict full go parity evidence and status" +``` + +--- + +## Plan Notes + +- Keep each capability independent and evidence-backed. +- Do not mark parity complete based on comments/table defaults alone. +- Prefer deterministic integration fixtures and bounded timeouts to avoid flaky parity closure.