diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/InboundScriptHost.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/InboundScriptHost.cs
index 98212fbb..984425ae 100644
--- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/InboundScriptHost.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/InboundScriptHost.cs
@@ -28,6 +28,14 @@ public class InboundScriptHost
///
public DatabaseAccessor Database { get; } = new();
+ ///
+ /// Leveled per-run logging. Editor mirror of
+ /// ZB.MOM.WW.ScadaBridge.InboundAPI.InboundScriptLogger (step logs design 2026-09-09 D4);
+ /// shares with the Test Run sandbox because only the signatures
+ /// matter here — analysis never invokes it.
+ ///
+ public SandboxLog Log { get; } = new();
+
///
/// The cancellation token for the operation.
///
diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxScriptHost.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxScriptHost.cs
index 9153edab..cce4cda0 100644
--- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxScriptHost.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxScriptHost.cs
@@ -91,9 +91,11 @@ public class SandboxScriptHost
///
/// Sandbox mirror of the site runtime's Log global (step logs design 2026-09-09 D4).
/// Present so a script that logs BINDS in the Test Run editor; lines go to the Test Run
- /// console pane and are never audited.
+ /// console pane and are never audited. Delegates to
+ /// exactly as the runtime's ScriptGlobals.Log => Instance.Log does, so
+ /// Log and Instance.Log are the same object here too.
///
- public SandboxLog Log { get; } = new();
+ public SandboxLog Log => Instance.Log;
}
///
diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/ScriptAnalysis/ScriptAnalysisServiceTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/ScriptAnalysis/ScriptAnalysisServiceTests.cs
index 257aba65..9601c2e4 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/ScriptAnalysis/ScriptAnalysisServiceTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/ScriptAnalysis/ScriptAnalysisServiceTests.cs
@@ -695,6 +695,40 @@ public class ScriptAnalysisServiceTests
Assert.DoesNotContain(resp.Markers, m => m.Code.StartsWith("SCADA"));
}
+ [Fact]
+ public void InboundScript_Log_DiagnosesClean()
+ {
+ // Flow Debugger step logs (design 2026-09-09 D4): `Log` is a shipped inbound-script
+ // global (InboundScriptContext.Log). The EDITOR host is a third mirror alongside the
+ // compile surface and the Test Run sandbox — without `Log` on InboundScriptHost a
+ // logging method script shows a spurious CS0103 while deploying and running fine.
+ var resp = _svc.Diagnose(new DiagnoseRequest(
+ Code: "Log.Info(\"x\");\n"
+ + "Log.Debug(\"d\");\n"
+ + "Log.Warn(\"w\", new System.Exception(\"boom\"));\n"
+ + "Log.Error(\"e\");",
+ Kind: ScriptKind.InboundApi));
+
+ Assert.DoesNotContain(resp.Markers, m => m.Code.StartsWith("CS"));
+ Assert.DoesNotContain(resp.Markers, m => m.Code.StartsWith("SCADA"));
+ }
+
+ [Fact]
+ public void SiteScript_Log_DiagnosesClean()
+ {
+ // The other half of GlobalsTypeFor: every non-inbound kind analyses against
+ // SandboxScriptHost, so the same `Log` global must resolve there too — both at
+ // the top level and via `Instance.Log`.
+ var resp = _svc.Diagnose(new DiagnoseRequest(
+ Code: "Log.Info(\"x\");\n"
+ + "Log.Warn(\"w\", new System.Exception(\"boom\"));\n"
+ + "Instance.Log.Info(\"via instance\");",
+ Kind: ScriptKind.Template));
+
+ Assert.DoesNotContain(resp.Markers, m => m.Code.StartsWith("CS"));
+ Assert.DoesNotContain(resp.Markers, m => m.Code.StartsWith("SCADA"));
+ }
+
[Fact]
public void InboundScript_Database_DiagnosesClean()
{
diff --git a/tests/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests/RoslynScriptCompilerTests.cs b/tests/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests/RoslynScriptCompilerTests.cs
index 7ca28a7b..ff4deb26 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests/RoslynScriptCompilerTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests/RoslynScriptCompilerTests.cs
@@ -140,7 +140,7 @@ public class RoslynScriptCompilerTests
}
[Fact]
- public void Compile_Empty_ForTheLogGlobal()
+ public void CompilesCleanly_ForTheLogGlobal()
{
// Flow Debugger step logs (design 2026-09-09 D4): `Log` is a script-reachable
// global on the runtime ScriptGlobals AND on ScriptRuntimeContext, so both the