Files
natsdotnet/docs/plans/2026-02-23-nats-strict-full-go-parity-plan.md
2026-02-23 14:27:04 -05:00

27 KiB

NATS Strict Full Go Parity Implementation Plan

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

Goal: Port all remaining NATS functionality gaps from Go to .NET at capability level (not table-status level), with behavior-complete implementation, unit/integration coverage, and synchronized parity documentation.

Architecture: Execute in dependency layers: inter-server fabric first, then MQTT wire/runtime parity, then JetStream runtime state machines, then storage/RAFT/cluster governance, then operational parity and docs synchronization. Every capability closes only when Behavior + Tests + Docs are complete.

Tech Stack: .NET 10, C# 14, xUnit 3, Shouldly, System.IO.Pipelines, ASP.NET Core monitoring endpoints, custom protocol parsers, integration socket fixtures.


Execution guardrails

  • Use @test-driven-development for each task.
  • If expected contracts and observed runtime behavior diverge, switch to @systematic-debugging before changing production code.
  • Keep one commit per task.
  • Run @verification-before-completion before final parity status updates.

Task 1: Add Strict Capability Inventory Guardrail

Files:

  • Create: docs/plans/2026-02-23-nats-strict-full-go-parity-map.md
  • Create: tests/NATS.Server.Tests/Parity/NatsStrictCapabilityInventoryTests.cs
  • Create: tests/NATS.Server.Tests/Parity/NatsCapabilityInventory.cs

Step 1: Write the failing test

[Fact]
public void Strict_capability_inventory_has_no_open_items_marked_done_without_behavior_and_tests()
{
    var report = NatsCapabilityInventory.Load(
        "docs/plans/2026-02-23-nats-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~NatsStrictCapabilityInventoryTests" -v minimal
Expected: FAIL because inventory map and validator are not yet present.

Step 3: Write minimal implementation

public sealed record CapabilityRow(string Capability, string Behavior, string Tests, string Docs);
public IReadOnlyList<CapabilityRow> InvalidRows => Rows.Where(r => r.Behavior != "done" && r.Docs == "closed").ToArray();

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~NatsStrictCapabilityInventoryTests" -v minimal
Expected: PASS.

Step 5: Commit

git add docs/plans/2026-02-23-nats-strict-full-go-parity-map.md tests/NATS.Server.Tests/Parity/NatsStrictCapabilityInventoryTests.cs tests/NATS.Server.Tests/Parity/NatsCapabilityInventory.cs
git commit -m "test: add strict nats capability inventory guardrail"

Task 2: Enforce Account-Scoped Remote Delivery

Files:

  • Modify: src/NATS.Server/NatsServer.cs
  • Modify: src/NATS.Server/Auth/Account.cs
  • Test: tests/NATS.Server.Tests/Routes/RouteAccountScopedDeliveryTests.cs
  • Test: tests/NATS.Server.Tests/Gateways/GatewayAccountScopedDeliveryTests.cs
  • Test: tests/NATS.Server.Tests/LeafNodes/LeafAccountScopedDeliveryTests.cs

Step 1: Write the failing test

[Fact]
public async Task Remote_message_delivery_uses_target_account_sublist_not_global_sublist()
{
    await using var fx = await InterServerAccountDeliveryFixture.StartAsync();
    var report = await fx.PublishAndObserveAsync();
    report.CrossAccountLeak.ShouldBeFalse();
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~AccountScopedDeliveryTests" -v minimal
Expected: FAIL because remote delivery currently resolves against global account only.

Step 3: Write minimal implementation

private void DeliverRemoteMessage(string account, string subject, string? replyTo, ReadOnlyMemory<byte> payload)
{
    var target = GetOrCreateAccount(account);
    var result = target.SubList.Match(subject);
    // deliver using result...
}

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~AccountScopedDeliveryTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/NatsServer.cs src/NATS.Server/Auth/Account.cs tests/NATS.Server.Tests/Routes/RouteAccountScopedDeliveryTests.cs tests/NATS.Server.Tests/Gateways/GatewayAccountScopedDeliveryTests.cs tests/NATS.Server.Tests/LeafNodes/LeafAccountScopedDeliveryTests.cs
git commit -m "feat: enforce account-scoped remote delivery semantics"

Task 3: Make Remote Interest Propagation Idempotent Under Reconnects

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/LeafNodes/LeafConnection.cs
  • Modify: src/NATS.Server/Subscriptions/SubList.cs
  • Test: tests/NATS.Server.Tests/Routes/RouteInterestIdempotencyTests.cs
  • Test: tests/NATS.Server.Tests/Gateways/GatewayInterestIdempotencyTests.cs
  • Test: tests/NATS.Server.Tests/LeafNodes/LeafInterestIdempotencyTests.cs

Step 1: Write the failing test

[Fact]
public async Task Duplicate_RSplus_or_reconnect_replay_does_not_double_count_remote_interest()
{
    await using var fx = await RouteInterestFixture.StartAsync();
    var count = await fx.ReplayInterestFramesAsync();
    count.ShouldBe(1);
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~InterestIdempotencyTests" -v minimal
Expected: FAIL due duplicate remote-interest accumulation.

Step 3: Write minimal implementation

// Key remote interest by (remoteServerId, account, subject, queue)
// and treat replay as upsert rather than increment.

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~InterestIdempotencyTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/Routes/RouteConnection.cs src/NATS.Server/Routes/RouteManager.cs src/NATS.Server/Gateways/GatewayConnection.cs src/NATS.Server/LeafNodes/LeafConnection.cs src/NATS.Server/Subscriptions/SubList.cs tests/NATS.Server.Tests/Routes/RouteInterestIdempotencyTests.cs tests/NATS.Server.Tests/Gateways/GatewayInterestIdempotencyTests.cs tests/NATS.Server.Tests/LeafNodes/LeafInterestIdempotencyTests.cs
git commit -m "feat: make inter-server interest propagation idempotent"

Task 4: Harden Gateway Reply Remap and Leaf Loop-Marker Transparency

Files:

  • Modify: src/NATS.Server/Gateways/ReplyMapper.cs
  • Modify: src/NATS.Server/LeafNodes/LeafLoopDetector.cs
  • Modify: src/NATS.Server/NatsServer.cs
  • Test: tests/NATS.Server.Tests/GatewayAdvancedRemapRuntimeTests.cs
  • Test: tests/NATS.Server.Tests/LeafNodes/LeafLoopTransparencyRuntimeTests.cs

Step 1: Write the failing test

[Fact]
public async Task Transport_internal_reply_and_loop_markers_never_leak_to_client_visible_subjects()
{
    await using var fx = await GatewayLeafMarkerFixture.StartAsync();
    var leak = await fx.PublishObserveLeakAsync();
    leak.ShouldBeFalse();
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~RemapRuntimeTests|FullyQualifiedName~LoopTransparencyRuntimeTests" -v minimal
Expected: FAIL if markers can leak on edge routing paths.

Step 3: Write minimal implementation

if (ReplyMapper.TryRestoreGatewayReply(replyTo, out var restored)) replyTo = restored;
if (LeafLoopDetector.TryUnmark(subject, out var unmarked)) subject = unmarked;

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~RemapRuntimeTests|FullyQualifiedName~LoopTransparencyRuntimeTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/Gateways/ReplyMapper.cs src/NATS.Server/LeafNodes/LeafLoopDetector.cs src/NATS.Server/NatsServer.cs tests/NATS.Server.Tests/GatewayAdvancedRemapRuntimeTests.cs tests/NATS.Server.Tests/LeafNodes/LeafLoopTransparencyRuntimeTests.cs
git commit -m "feat: harden gateway reply remap and leaf loop transparency"

Task 5: Replace Line-Based MQTT With Packet-Level Parser/Writer

Files:

  • Create: src/NATS.Server/Mqtt/MqttPacketReader.cs
  • Create: src/NATS.Server/Mqtt/MqttPacketWriter.cs
  • Modify: src/NATS.Server/Mqtt/MqttProtocolParser.cs
  • Test: tests/NATS.Server.Tests/Mqtt/MqttPacketParserTests.cs
  • Test: tests/NATS.Server.Tests/Mqtt/MqttPacketWriterTests.cs

Step 1: Write the failing test

[Fact]
public void Connect_packet_fixed_header_and_remaining_length_parse_correctly()
{
    var packet = MqttPacketReader.Read(ConnectPacketBytes.Sample);
    packet.Type.ShouldBe(MqttControlPacketType.Connect);
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttPacketParserTests|FullyQualifiedName~MqttPacketWriterTests" -v minimal
Expected: FAIL because packet-level parser/writer do not yet exist.

Step 3: Write minimal implementation

var first = buffer[0];
var type = (MqttControlPacketType)(first >> 4);
var remainingLength = DecodeRemainingLength(buffer[1..], out var consumed);

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttPacketParserTests|FullyQualifiedName~MqttPacketWriterTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/Mqtt/MqttPacketReader.cs src/NATS.Server/Mqtt/MqttPacketWriter.cs src/NATS.Server/Mqtt/MqttProtocolParser.cs tests/NATS.Server.Tests/Mqtt/MqttPacketParserTests.cs tests/NATS.Server.Tests/Mqtt/MqttPacketWriterTests.cs
git commit -m "feat: implement mqtt packet-level parser and writer"

Task 6: Implement MQTT Session and QoS Acknowledgement Runtime

Files:

  • Modify: src/NATS.Server/Mqtt/MqttConnection.cs
  • Modify: src/NATS.Server/Mqtt/MqttListener.cs
  • Modify: src/NATS.Server/MqttOptions.cs
  • Test: tests/NATS.Server.Tests/Mqtt/MqttSessionRuntimeTests.cs
  • Test: tests/NATS.Server.Tests/Mqtt/MqttQosAckRuntimeTests.cs

Step 1: Write the failing test

[Fact]
public async Task Qos1_publish_receives_puback_and_redelivery_on_session_reconnect_when_unacked()
{
    await using var fx = await MqttSessionFixture.StartAsync();
    var report = await fx.RunQosScenarioAsync();
    report.PubAckObserved.ShouldBeTrue();
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttSessionRuntimeTests|FullyQualifiedName~MqttQosAckRuntimeTests" -v minimal
Expected: FAIL because current MQTT runtime lacks session/QoS state machine behavior.

Step 3: Write minimal implementation

if (packet.Qos == 1)
{
    _pendingPublishes[packet.PacketId] = packet;
    await SendPubAckAsync(packet.PacketId, ct);
}

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttSessionRuntimeTests|FullyQualifiedName~MqttQosAckRuntimeTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/Mqtt/MqttConnection.cs src/NATS.Server/Mqtt/MqttListener.cs src/NATS.Server/MqttOptions.cs tests/NATS.Server.Tests/Mqtt/MqttSessionRuntimeTests.cs tests/NATS.Server.Tests/Mqtt/MqttQosAckRuntimeTests.cs
git commit -m "feat: implement mqtt session and qos ack runtime semantics"

Task 7: Implement MQTT Auth/TLS/Keepalive Contract Integration

Files:

  • Modify: src/NATS.Server/Mqtt/MqttConnection.cs
  • Modify: src/NATS.Server/Mqtt/MqttListener.cs
  • Modify: src/NATS.Server/NatsServer.cs
  • Modify: src/NATS.Server/Auth/AuthService.cs
  • Test: tests/NATS.Server.Tests/Mqtt/MqttAuthIntegrationTests.cs
  • Test: tests/NATS.Server.Tests/Mqtt/MqttKeepAliveTests.cs

Step 1: Write the failing test

[Fact]
public async Task Invalid_mqtt_credentials_or_keepalive_timeout_close_session_with_protocol_error()
{
    await using var fx = await MqttAuthFixture.StartAsync();
    var result = await fx.RunInvalidAuthAndKeepAliveScenarioAsync();
    result.ConnectionClosed.ShouldBeTrue();
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttAuthIntegrationTests|FullyQualifiedName~MqttKeepAliveTests" -v minimal
Expected: FAIL because MQTT auth and keepalive are not fully enforced.

Step 3: Write minimal implementation

if (!TryAuthenticateMqtt(connectPacket, out _))
    return await CloseWithReasonAsync("mqtt auth failed", ct);

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~MqttAuthIntegrationTests|FullyQualifiedName~MqttKeepAliveTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/Mqtt/MqttConnection.cs src/NATS.Server/Mqtt/MqttListener.cs src/NATS.Server/NatsServer.cs src/NATS.Server/Auth/AuthService.cs tests/NATS.Server.Tests/Mqtt/MqttAuthIntegrationTests.cs tests/NATS.Server.Tests/Mqtt/MqttKeepAliveTests.cs
git commit -m "feat: enforce mqtt auth tls and keepalive semantics"

Task 8: Implement Distinct JetStream Retention Runtime Semantics

Files:

  • Modify: src/NATS.Server/JetStream/StreamManager.cs
  • Modify: src/NATS.Server/JetStream/ConsumerManager.cs
  • Test: tests/NATS.Server.Tests/JetStream/JetStreamRetentionRuntimeStrictParityTests.cs

Step 1: Write the failing test

[Fact]
public async Task Limits_interest_and_workqueue_retention_diverge_by_runtime_contract()
{
    await using var fx = await JetStreamRetentionStrictFixture.StartAsync();
    var report = await fx.RunPolicyMatrixAsync();
    report.PolicyViolations.ShouldBeEmpty();
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamRetentionRuntimeStrictParityTests" -v minimal
Expected: FAIL because WorkQueue/Interest currently share limits retention path.

Step 3: Write minimal implementation

switch (stream.Config.Retention)
{
    case RetentionPolicy.Interest: ApplyInterestRetentionWithConsumerInterest(stream, consumerState); break;
    case RetentionPolicy.WorkQueue: ApplyWorkQueueRetentionWithAckState(stream, consumerState); break;
    default: ApplyLimitsRetention(stream, nowUtc); break;
}

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamRetentionRuntimeStrictParityTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/JetStream/StreamManager.cs src/NATS.Server/JetStream/ConsumerManager.cs tests/NATS.Server.Tests/JetStream/JetStreamRetentionRuntimeStrictParityTests.cs
git commit -m "feat: implement strict retention runtime parity for jetstream"

Task 9: Harden JetStream Consumer Ack/Backoff/Replay/Flow State Machine

Files:

  • Modify: src/NATS.Server/JetStream/Consumers/AckProcessor.cs
  • Modify: src/NATS.Server/JetStream/Consumers/PullConsumerEngine.cs
  • Modify: src/NATS.Server/JetStream/Consumers/PushConsumerEngine.cs
  • Modify: src/NATS.Server/JetStream/ConsumerManager.cs
  • Test: tests/NATS.Server.Tests/JetStream/JetStreamConsumerStateMachineStrictParityTests.cs

Step 1: Write the failing test

[Fact]
public async Task Ack_redelivery_backoff_and_replay_timing_follow_monotonic_consumer_state_machine_rules()
{
    await using var fx = await ConsumerStateMachineFixture.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~JetStreamConsumerStateMachineStrictParityTests" -v minimal
Expected: FAIL on pending-floor/replay/backoff edge cases.

Step 3: Write minimal implementation

if (config.MaxDeliver > 0 && deliveries > config.MaxDeliver) TerminatePending(sequence);
if (config.AckPolicy == AckPolicy.All) AdvanceAckFloor(sequence);

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamConsumerStateMachineStrictParityTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/JetStream/Consumers/AckProcessor.cs src/NATS.Server/JetStream/Consumers/PullConsumerEngine.cs src/NATS.Server/JetStream/Consumers/PushConsumerEngine.cs src/NATS.Server/JetStream/ConsumerManager.cs tests/NATS.Server.Tests/JetStream/JetStreamConsumerStateMachineStrictParityTests.cs
git commit -m "feat: harden jetstream consumer state machine parity"

Task 10: Harden JetStream Mirror/Source Runtime 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/JetStreamMirrorSourceStrictRuntimeTests.cs

Step 1: Write the failing test

[Fact]
public async Task Mirror_source_transform_and_cross_account_filters_follow_runtime_contract()
{
    await using var fx = await MirrorSourceStrictFixture.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~JetStreamMirrorSourceStrictRuntimeTests" -v minimal
Expected: FAIL for cross-account and filter-transform edge combinations.

Step 3: Write minimal implementation

if (!SourceAccountAuthorized(sourceConfig, message.Account)) return;
if (!FilterMatches(sourceConfig, message.Subject)) return;

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamMirrorSourceStrictRuntimeTests" -v minimal
Expected: PASS.

Step 5: Commit

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/JetStreamMirrorSourceStrictRuntimeTests.cs
git commit -m "feat: complete jetstream mirror source strict runtime parity"

Task 11: Implement FileStore Durable Invariants and Recovery Contract

Files:

  • Modify: src/NATS.Server/JetStream/Storage/FileStore.cs
  • Modify: src/NATS.Server/JetStream/Storage/FileStoreBlock.cs
  • Test: tests/NATS.Server.Tests/JetStream/JetStreamFileStoreRecoveryStrictParityTests.cs
  • Test: tests/NATS.Server.Tests/JetStream/JetStreamFileStoreInvariantTests.cs

Step 1: Write the failing test

[Fact]
public async Task Filestore_recovery_preserves_sequence_subject_index_and_integrity_after_prune_and_restart_cycles()
{
    var report = await FileStoreStrictFixture.RunRecoveryCycleAsync();
    report.InvariantViolations.ShouldBeEmpty();
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamFileStoreRecoveryStrictParityTests|FullyQualifiedName~JetStreamFileStoreInvariantTests" -v minimal
Expected: FAIL on restart/prune/index invariant checks.

Step 3: Write minimal implementation

PersistManifestVersioned();
ValidateSequenceAndSubjectIndexOnLoad();

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamFileStoreRecoveryStrictParityTests|FullyQualifiedName~JetStreamFileStoreInvariantTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/JetStream/Storage/FileStore.cs src/NATS.Server/JetStream/Storage/FileStoreBlock.cs tests/NATS.Server.Tests/JetStream/JetStreamFileStoreRecoveryStrictParityTests.cs tests/NATS.Server.Tests/JetStream/JetStreamFileStoreInvariantTests.cs
git commit -m "feat: enforce filestore durability and recovery invariants"

Task 12: Implement RAFT Quorum/NextIndex/Snapshot/Membership 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/RaftSnapshotStore.cs
  • Test: tests/NATS.Server.Tests/Raft/RaftStrictConsensusRuntimeTests.cs
  • Test: tests/NATS.Server.Tests/Raft/RaftStrictConvergenceRuntimeTests.cs

Step 1: Write the failing test

[Fact]
public async Task Quorum_and_nextindex_rules_gate_commit_visibility_and_snapshot_catchup_convergence()
{
    var report = await RaftStrictFixture.RunConsensusScenarioAsync();
    report.InvariantViolations.ShouldBeEmpty();
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~RaftStrictConsensusRuntimeTests|FullyQualifiedName~RaftStrictConvergenceRuntimeTests" -v minimal
Expected: FAIL due simplified in-memory quorum and convergence behavior.

Step 3: Write minimal implementation

if (!HasQuorum(appendAcks)) return CommitRejected();
nextIndex[follower] = ComputeNextIndexOnMismatch(followerState);

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~RaftStrictConsensusRuntimeTests|FullyQualifiedName~RaftStrictConvergenceRuntimeTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/Raft/RaftNode.cs src/NATS.Server/Raft/RaftReplicator.cs src/NATS.Server/Raft/RaftTransport.cs src/NATS.Server/Raft/RaftSnapshotStore.cs tests/NATS.Server.Tests/Raft/RaftStrictConsensusRuntimeTests.cs tests/NATS.Server.Tests/Raft/RaftStrictConvergenceRuntimeTests.cs
git commit -m "feat: implement strict raft consensus and convergence parity"

Task 13: Implement JetStream Meta/Replica Governance Runtime Contracts

Files:

  • Modify: src/NATS.Server/JetStream/Cluster/JetStreamMetaGroup.cs
  • Modify: src/NATS.Server/JetStream/Cluster/StreamReplicaGroup.cs
  • Modify: src/NATS.Server/JetStream/StreamManager.cs
  • Test: tests/NATS.Server.Tests/JetStream/JetStreamMetaGovernanceStrictParityTests.cs
  • Test: tests/NATS.Server.Tests/JetStream/JetStreamReplicaGovernanceStrictParityTests.cs

Step 1: Write the failing test

[Fact]
public async Task Meta_and_replica_governance_actions_reflect_committed_state_transitions()
{
    await using var fx = await JetStreamGovernanceFixture.StartAsync();
    var report = await fx.RunStepdownPlacementScenarioAsync();
    report.InvariantViolations.ShouldBeEmpty();
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamMetaGovernanceStrictParityTests|FullyQualifiedName~JetStreamReplicaGovernanceStrictParityTests" -v minimal
Expected: FAIL due placeholder governance behavior.

Step 3: Write minimal implementation

public void StepDown() => _leaderId = ElectNextLeader();

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~JetStreamMetaGovernanceStrictParityTests|FullyQualifiedName~JetStreamReplicaGovernanceStrictParityTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/JetStream/Cluster/JetStreamMetaGroup.cs src/NATS.Server/JetStream/Cluster/StreamReplicaGroup.cs src/NATS.Server/JetStream/StreamManager.cs tests/NATS.Server.Tests/JetStream/JetStreamMetaGovernanceStrictParityTests.cs tests/NATS.Server.Tests/JetStream/JetStreamReplicaGovernanceStrictParityTests.cs
git commit -m "feat: implement jetstream governance runtime parity semantics"

Task 14: Replace Synthetic Profiling and Close Runtime Option Drift

Files:

  • Modify: src/NATS.Server/Monitoring/PprofHandler.cs
  • Modify: src/NATS.Server/Monitoring/MonitorServer.cs
  • Modify: src/NATS.Server/NatsServer.cs
  • Modify: src/NATS.Server/Configuration/ConfigReloader.cs
  • Test: tests/NATS.Server.Tests/Monitoring/PprofRuntimeParityTests.cs
  • Test: tests/NATS.Server.Tests/ConfigRuntimeParityTests.cs

Step 1: Write the failing test

[Fact]
public async Task Profiling_endpoint_returns_runtime_profile_artifacts_and_config_options_map_to_runtime_behavior()
{
    var report = await OperationalParityFixture.RunAsync();
    report.InvariantViolations.ShouldBeEmpty();
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~PprofRuntimeParityTests|FullyQualifiedName~ConfigRuntimeParityTests" -v minimal
Expected: FAIL due synthetic profiling output and option-runtime mismatches.

Step 3: Write minimal implementation

public byte[] CaptureCpuProfile(int seconds) => _runtimeProfiler.Capture(seconds);

Step 4: Run test to verify it passes

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~PprofRuntimeParityTests|FullyQualifiedName~ConfigRuntimeParityTests" -v minimal
Expected: PASS.

Step 5: Commit

git add src/NATS.Server/Monitoring/PprofHandler.cs src/NATS.Server/Monitoring/MonitorServer.cs src/NATS.Server/NatsServer.cs src/NATS.Server/Configuration/ConfigReloader.cs tests/NATS.Server.Tests/Monitoring/PprofRuntimeParityTests.cs tests/NATS.Server.Tests/ConfigRuntimeParityTests.cs
git commit -m "feat: add runtime profiling parity and close config runtime drift"

Task 15: Final Verification and Documentation Synchronization

Files:

  • Modify: differences.md
  • Modify: docs/plans/2026-02-23-jetstream-remaining-parity-map.md
  • Modify: docs/plans/2026-02-23-jetstream-remaining-parity-verification.md
  • Modify: docs/plans/2026-02-23-nats-strict-full-go-parity-map.md
  • Modify: tests/NATS.Server.Tests/DifferencesParityClosureTests.cs

Step 1: Write the failing test

[Fact]
public void Differences_and_strict_capability_maps_have_no_claims_without_behavior_and_test_evidence()
{
    var report = StrictParityDocInspector.Load("differences.md", "docs/plans/2026-02-23-nats-strict-full-go-parity-map.md");
    report.DriftRows.ShouldBeEmpty();
}

Step 2: Run test to verify it fails

Run: dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~DifferencesParityClosureTests|FullyQualifiedName~NatsStrictCapabilityInventoryTests" -v minimal
Expected: FAIL until docs are synchronized with implemented behavior.

Step 3: Update parity docs and evidence maps

Run: rg -n "remaining|incomplete|baseline|stub|placeholder" differences.md docs/plans/2026-02-23-nats-strict-full-go-parity-map.md
Expected: only intentionally deferred items remain and each has explicit blocker rationale.

Step 4: Run full verification

Run: dotnet test -v minimal
Expected: PASS.

Step 5: Commit

git add differences.md docs/plans/2026-02-23-jetstream-remaining-parity-map.md docs/plans/2026-02-23-jetstream-remaining-parity-verification.md docs/plans/2026-02-23-nats-strict-full-go-parity-map.md tests/NATS.Server.Tests/DifferencesParityClosureTests.cs
git commit -m "docs: synchronize strict full go parity evidence and status"

Plan Notes

  • Prefer small, behavior-focused deltas in each task.
  • Do not mark any capability as closed based on type signatures, placeholders, or route registration alone.
  • Keep runtime integration fixtures deterministic and timeout-bounded to avoid flaky parity claims.