docs: add strict full go parity implementation plan

This commit is contained in:
Joseph Doherty
2026-02-23 14:27:04 -05:00
parent ffb165fd8a
commit f76b599e2d

View File

@@ -0,0 +1,703 @@
# 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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```csharp
// 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**
```bash
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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```csharp
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**
```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/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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```csharp
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**
```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/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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```csharp
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**
```bash
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**
```csharp
[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**
```bash
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.