diff --git a/reports/current.md b/reports/current.md
index ea1a213..50cdb85 100644
--- a/reports/current.md
+++ b/reports/current.md
@@ -1,6 +1,6 @@
# NATS .NET Porting Status Report
-Generated: 2026-02-27 10:16:59 UTC
+Generated: 2026-02-27 10:17:36 UTC
## Modules (12 total)
diff --git a/reports/report_2dd2321.md b/reports/report_2dd2321.md
new file mode 100644
index 0000000..50cdb85
--- /dev/null
+++ b/reports/report_2dd2321.md
@@ -0,0 +1,35 @@
+# NATS .NET Porting Status Report
+
+Generated: 2026-02-27 10:17:36 UTC
+
+## Modules (12 total)
+
+| Status | Count |
+|--------|-------|
+| verified | 12 |
+
+## Features (3673 total)
+
+| Status | Count |
+|--------|-------|
+| unknown | 3394 |
+| verified | 279 |
+
+## Unit Tests (3257 total)
+
+| Status | Count |
+|--------|-------|
+| deferred | 2680 |
+| n_a | 187 |
+| verified | 390 |
+
+## Library Mappings (36 total)
+
+| Status | Count |
+|--------|-------|
+| mapped | 36 |
+
+
+## Overall Progress
+
+**868/6942 items complete (12.5%)**
diff --git a/tools/NatsNet.PortTracker/Audit/FeatureClassifier.cs b/tools/NatsNet.PortTracker/Audit/FeatureClassifier.cs
new file mode 100644
index 0000000..75591c3
--- /dev/null
+++ b/tools/NatsNet.PortTracker/Audit/FeatureClassifier.cs
@@ -0,0 +1,91 @@
+namespace NatsNet.PortTracker.Audit;
+
+///
+/// Classifies features by inspecting the SourceIndexer for their .NET implementation status.
+/// Priority: n_a lookup -> method-not-found -> stub detection -> verified.
+///
+public sealed class FeatureClassifier
+{
+ public record ClassificationResult(string Status, string Reason);
+
+ public record FeatureRecord(
+ long Id,
+ string DotnetClass,
+ string DotnetMethod,
+ string GoFile,
+ string GoMethod);
+
+ private readonly SourceIndexer _indexer;
+
+ // N/A lookup: (goMethod pattern) -> reason
+ // Checked case-insensitively against go_method
+ private static readonly Dictionary NaByGoMethod = new(StringComparer.OrdinalIgnoreCase)
+ {
+ ["Noticef"] = ".NET uses Microsoft.Extensions.Logging",
+ ["Debugf"] = ".NET uses Microsoft.Extensions.Logging",
+ ["Tracef"] = ".NET uses Microsoft.Extensions.Logging",
+ ["Warnf"] = ".NET uses Microsoft.Extensions.Logging",
+ ["Errorf"] = ".NET uses Microsoft.Extensions.Logging",
+ ["Fatalf"] = ".NET uses Microsoft.Extensions.Logging",
+ };
+
+ // N/A lookup: go_file + go_method patterns
+ private static readonly List<(Func Match, string Reason)> NaPatterns =
+ [
+ // Signal handling — .NET uses IHostApplicationLifetime
+ (f => f.GoMethod.Equals("handleSignals", StringComparison.OrdinalIgnoreCase), ".NET uses IHostApplicationLifetime"),
+ (f => f.GoMethod.Equals("processSignal", StringComparison.OrdinalIgnoreCase), ".NET uses IHostApplicationLifetime"),
+ ];
+
+ public FeatureClassifier(SourceIndexer indexer)
+ {
+ _indexer = indexer;
+ }
+
+ ///
+ /// Classify a single feature. Returns status and reason.
+ ///
+ public ClassificationResult Classify(FeatureRecord feature)
+ {
+ // 1. N/A lookup — check go_method against known patterns
+ if (NaByGoMethod.TryGetValue(feature.GoMethod, out var naReason))
+ return new ClassificationResult("n_a", naReason);
+
+ foreach (var (match, reason) in NaPatterns)
+ {
+ if (match(feature))
+ return new ClassificationResult("n_a", reason);
+ }
+
+ // 2. Handle comma-separated dotnet_class (e.g. "ClosedRingBuffer,ClosedClient")
+ var classNames = feature.DotnetClass.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+ var methodName = feature.DotnetMethod;
+
+ // Try each class name
+ foreach (var className in classNames)
+ {
+ var methods = _indexer.Lookup(className, methodName);
+ if (methods.Count > 0)
+ {
+ // Found the method — classify based on body analysis
+ // Use the "best" match: prefer non-stub over stub
+ var best = methods.OrderByDescending(m => m.StatementCount).First();
+
+ if (best.IsStub)
+ return new ClassificationResult("stub", $"Body is throw NotImplementedException at {Path.GetFileName(best.FilePath)}:{best.LineNumber}");
+
+ if (best.IsPartial)
+ return new ClassificationResult("stub", $"Partial implementation with NotImplementedException at {Path.GetFileName(best.FilePath)}:{best.LineNumber}");
+
+ return new ClassificationResult("verified", $"Method found with {best.StatementCount} statement(s) at {Path.GetFileName(best.FilePath)}:{best.LineNumber}");
+ }
+ }
+
+ // 3. Method not found — check if any class exists
+ var anyClassFound = classNames.Any(c => _indexer.HasClass(c));
+ if (anyClassFound)
+ return new ClassificationResult("deferred", "Class exists but method not found");
+
+ return new ClassificationResult("deferred", "Class not found in .NET source");
+ }
+}