diff --git a/tests/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests/CachingScriptMetadataResolverTests.cs b/tests/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests/CachingScriptMetadataResolverTests.cs
index b35b1c8d..f2b0be07 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests/CachingScriptMetadataResolverTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests/CachingScriptMetadataResolverTests.cs
@@ -89,4 +89,66 @@ public class CachingScriptMetadataResolverTests
var sut = new CachingScriptMetadataResolver(new CountingResolver());
Assert.True(sut.ResolveMissingAssemblies);
}
+
+ ///
+ /// The decisive regression: with options shaped like the real compile
+ /// surfaces (small explicit set, large transitive closure), the FIRST
+ /// compile resolves the closure through the resolver and every subsequent
+ /// compile — same or different code — resolves NOTHING. Before the fix,
+ /// every compile re-resolved the full closure (measured: 74 fresh
+ /// PortableExecutableReferences per compile on Roslyn 5.0.0).
+ /// A probe wraps the DEFAULT resolver so the test also proves resolution
+ /// actually flows through this path at all (first > 0) — guarding against
+ /// the whole mechanism silently changing in a Roslyn upgrade.
+ ///
+ [Fact]
+ public void Compile_RepeatAndDistinctScripts_ResolveClosureOnlyOnce()
+ {
+ var probe = new ProbeResolver(ScriptOptions.Default.MetadataResolver);
+ var caching = new CachingScriptMetadataResolver(probe);
+
+ var options = ScriptOptions.Default
+ .WithReferences(
+ typeof(object).Assembly,
+ typeof(Enumerable).Assembly,
+ typeof(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo).Assembly)
+ .WithImports("System", "System.Linq")
+ .WithMetadataResolver(caching);
+
+ long CompileAndCount(string code)
+ {
+ long before = probe.MissingCalls;
+ var script = Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.Create