7fd44f0fa7
U2 (Critical): RoslynVirtualTagEvaluator ran scripts with a CancellationToken that a synchronous Roslyn script can never observe, so one CPU-bound/infinite- loop virtual-tag script hung the owning VirtualTagActor forever (no timeout, no recovery). Route evaluation through the existing TimedScriptEvaluator (Task.Run + WaitAsync) so the wall-clock budget is real; a runaway script now returns Bad within the timeout instead of wedging the actor. U3 (High): the live path cached evaluators in a raw ConcurrentDictionary never cleared on republish, leaking a collectible AssemblyLoadContext per edited script forever. Swap in the purpose-built CompiledScriptCache (Lazy single- compile, dispose-on-Clear) and add an apply-boundary clear: a new narrow IScriptCacheOwner seam the VirtualTagHostActor calls on each ApplyVirtualTags generation (mirrors ScriptedAlarmEngine's per-generation clear). Tests: infinite-loop-fails-within-timeout (bounded by WaitAsync so a regression fails instead of hanging), happy-path-after-wrapping, ClearCompiledScripts- empties-cache, and a host-actor wiring guard asserting each apply generation calls ClearCompiledScripts (theme #1 production-caller assertion). Host.Integration VT suite 18/18, Runtime VT suite 12/12.